@yushaw/sanqian-chat 0.2.19 → 0.2.21
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/core/index.d.mts +2 -0
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.js +46 -1
- package/dist/core/index.mjs +46 -1
- package/dist/renderer/index.d.mts +11 -3
- package/dist/renderer/index.d.ts +11 -3
- package/dist/renderer/index.js +619 -358
- package/dist/renderer/index.mjs +577 -317
- package/package.json +2 -2
- package/src/renderer/styles/chat.css +39 -0
- package/src/renderer/styles/coreCss.ts +39 -0
- package/src/renderer/styles/safe.css +39 -0
- package/src/renderer/styles/variables.css +10 -0
package/dist/renderer/index.js
CHANGED
|
@@ -81,7 +81,8 @@ __export(renderer_exports, {
|
|
|
81
81
|
useResourcePicker: () => useResourcePicker,
|
|
82
82
|
useStandaloneI18n: () => useStandaloneI18n,
|
|
83
83
|
useStandaloneTheme: () => useStandaloneTheme,
|
|
84
|
-
useTheme: () => useTheme
|
|
84
|
+
useTheme: () => useTheme,
|
|
85
|
+
useWindowDragLock: () => useWindowDragLock
|
|
85
86
|
});
|
|
86
87
|
module.exports = __toCommonJS(renderer_exports);
|
|
87
88
|
|
|
@@ -228,10 +229,12 @@ function useChat(options) {
|
|
|
228
229
|
case "start": {
|
|
229
230
|
currentRunIdRef.current = event.run_id;
|
|
230
231
|
if (pendingCancelRef.current) {
|
|
231
|
-
const pendingCancel = pendingCancelFnRef.current;
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
232
|
+
const pendingCancel = pendingCancelFnRef.current || cancelRef.current;
|
|
233
|
+
if (pendingCancel) {
|
|
234
|
+
clearPendingCancel();
|
|
235
|
+
pendingCancel();
|
|
236
|
+
cancelRef.current = null;
|
|
237
|
+
}
|
|
235
238
|
}
|
|
236
239
|
break;
|
|
237
240
|
}
|
|
@@ -648,8 +651,11 @@ function useChat(options) {
|
|
|
648
651
|
}
|
|
649
652
|
}
|
|
650
653
|
}, [clearPendingCancel, flushTypewriter, onConversationChange, onError, resetStreamBuffers]);
|
|
651
|
-
const
|
|
652
|
-
|
|
654
|
+
const trySendMessage = (0, import_react.useCallback)(async (content, sendOptions) => {
|
|
655
|
+
const trimmedContent = content.trim();
|
|
656
|
+
const hasAttachedResources = (sendOptions?.attachedResources?.length ?? 0) > 0;
|
|
657
|
+
const hasSessionResources = sessionResources.length > 0;
|
|
658
|
+
if (!trimmedContent && !hasAttachedResources && !hasSessionResources) return false;
|
|
653
659
|
setError(null);
|
|
654
660
|
clearPendingCancel();
|
|
655
661
|
suppressStreamRef.current = false;
|
|
@@ -662,7 +668,7 @@ function useChat(options) {
|
|
|
662
668
|
const userMessage = {
|
|
663
669
|
id: crypto.randomUUID(),
|
|
664
670
|
role: "user",
|
|
665
|
-
content:
|
|
671
|
+
content: trimmedContent,
|
|
666
672
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
667
673
|
attachedResources: sendOptions?.attachedResources?.length ? sendOptions.attachedResources : void 0
|
|
668
674
|
};
|
|
@@ -676,14 +682,16 @@ function useChat(options) {
|
|
|
676
682
|
blocks: [],
|
|
677
683
|
isComplete: false
|
|
678
684
|
};
|
|
679
|
-
|
|
685
|
+
const shouldRenderUserMessage = trimmedContent.length > 0 || hasAttachedResources;
|
|
686
|
+
setMessages(
|
|
687
|
+
(prev) => shouldRenderUserMessage ? [...prev, userMessage, assistantMessage] : [...prev, assistantMessage]
|
|
688
|
+
);
|
|
680
689
|
setIsLoading(true);
|
|
681
690
|
setIsStreaming(true);
|
|
682
691
|
const sessionResourceIds = sessionResources.map((r) => r.fullId);
|
|
683
692
|
const savedSessionResources = sessionResourceIds.length > 0 ? [...sessionResources] : null;
|
|
684
693
|
try {
|
|
685
694
|
if (!adapter.isConnected()) await adapter.connect();
|
|
686
|
-
const trimmedContent = content.trim();
|
|
687
695
|
const shouldSendHistory = !conversationIdRef.current;
|
|
688
696
|
const historyMessages = shouldSendHistory ? messagesRef.current.filter((m) => m.role === "user" || m.role === "assistant").map((m) => ({ role: m.role, content: m.content })) : [];
|
|
689
697
|
const apiMessages = [...historyMessages, { role: "user", content: trimmedContent }];
|
|
@@ -704,6 +712,12 @@ function useChat(options) {
|
|
|
704
712
|
}
|
|
705
713
|
);
|
|
706
714
|
cancelRef.current = cancel;
|
|
715
|
+
if (pendingCancelRef.current) {
|
|
716
|
+
clearPendingCancel();
|
|
717
|
+
cancel();
|
|
718
|
+
cancelRef.current = null;
|
|
719
|
+
}
|
|
720
|
+
return true;
|
|
707
721
|
} catch (err) {
|
|
708
722
|
const errorMessage = err instanceof Error ? err.message : "Failed to send message";
|
|
709
723
|
setError(errorMessage);
|
|
@@ -720,8 +734,12 @@ function useChat(options) {
|
|
|
720
734
|
}
|
|
721
735
|
setIsLoading(false);
|
|
722
736
|
setIsStreaming(false);
|
|
737
|
+
return false;
|
|
723
738
|
}
|
|
724
739
|
}, [adapter, clearPendingCancel, handleStreamEvent, onError, resetStreamBuffers, sessionResources]);
|
|
740
|
+
const sendMessage = (0, import_react.useCallback)(async (content, sendOptions) => {
|
|
741
|
+
await trySendMessage(content, sendOptions);
|
|
742
|
+
}, [trySendMessage]);
|
|
725
743
|
const stopStreaming = (0, import_react.useCallback)(() => {
|
|
726
744
|
const shouldDelayCancel = !currentRunIdRef.current;
|
|
727
745
|
if (shouldDelayCancel) {
|
|
@@ -860,6 +878,7 @@ function useChat(options) {
|
|
|
860
878
|
conversationTitle,
|
|
861
879
|
pendingInterrupt,
|
|
862
880
|
sendMessage,
|
|
881
|
+
trySendMessage,
|
|
863
882
|
stopStreaming,
|
|
864
883
|
clearMessages,
|
|
865
884
|
setError,
|
|
@@ -1398,6 +1417,35 @@ var CSS_VARIABLES = `/**
|
|
|
1398
1417
|
user-select: text;
|
|
1399
1418
|
}
|
|
1400
1419
|
|
|
1420
|
+
/* ========================================
|
|
1421
|
+
Draggable Regions (Electron)
|
|
1422
|
+
======================================== */
|
|
1423
|
+
.chat-drag-region {
|
|
1424
|
+
-webkit-app-region: drag;
|
|
1425
|
+
}
|
|
1426
|
+
|
|
1427
|
+
/*
|
|
1428
|
+
* Interactive descendants inside drag regions must explicitly opt out of drag,
|
|
1429
|
+
* otherwise icon-only click targets can become non-clickable in Electron.
|
|
1430
|
+
*/
|
|
1431
|
+
.chat-drag-region button,
|
|
1432
|
+
.chat-drag-region button *,
|
|
1433
|
+
.chat-drag-region a,
|
|
1434
|
+
.chat-drag-region a *,
|
|
1435
|
+
.chat-drag-region input,
|
|
1436
|
+
.chat-drag-region textarea,
|
|
1437
|
+
.chat-drag-region select,
|
|
1438
|
+
.chat-drag-region [role="button"],
|
|
1439
|
+
.chat-drag-region [role="button"] * {
|
|
1440
|
+
-webkit-app-region: no-drag;
|
|
1441
|
+
}
|
|
1442
|
+
|
|
1443
|
+
/* Modal overlays should get click priority over drag regions. */
|
|
1444
|
+
:root[data-window-drag-locked="true"] .chat-drag-region {
|
|
1445
|
+
-webkit-app-region: no-drag !important;
|
|
1446
|
+
pointer-events: none !important;
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1401
1449
|
/* ========================================
|
|
1402
1450
|
Font Size Scaling
|
|
1403
1451
|
Applies zoom to scale entire chat UI including rem units.
|
|
@@ -1593,6 +1641,16 @@ code {
|
|
|
1593
1641
|
animation: chat-cursor-breathing 1s ease-in-out infinite;
|
|
1594
1642
|
}
|
|
1595
1643
|
|
|
1644
|
+
/* Streaming cursor - version-agnostic fallback (works across streamdown 1.x/2.x) */
|
|
1645
|
+
.chat-streaming-cursor {
|
|
1646
|
+
--streamdown-caret: '\u258C';
|
|
1647
|
+
}
|
|
1648
|
+
.chat-streaming-cursor > *:last-child::after {
|
|
1649
|
+
content: var(--streamdown-caret, '\u258C');
|
|
1650
|
+
color: var(--chat-accent) !important;
|
|
1651
|
+
animation: chat-cursor-breathing 1s ease-in-out infinite !important;
|
|
1652
|
+
}
|
|
1653
|
+
|
|
1596
1654
|
@keyframes chat-fade-in {
|
|
1597
1655
|
from {
|
|
1598
1656
|
opacity: 0;
|
|
@@ -5132,6 +5190,8 @@ function useFocusPersistence({
|
|
|
5132
5190
|
const container = containerRef.current;
|
|
5133
5191
|
if (!container) return;
|
|
5134
5192
|
const handleClick = (e) => {
|
|
5193
|
+
if (e.button !== 0 || e.ctrlKey) return;
|
|
5194
|
+
if (!(e.target instanceof Element)) return;
|
|
5135
5195
|
const target = e.target;
|
|
5136
5196
|
if (!container.contains(target)) return;
|
|
5137
5197
|
if (target.closest('button, a, input, textarea, [contenteditable], [role="menu"], [role="dialog"], [role="listbox"]')) {
|
|
@@ -5486,6 +5546,50 @@ function useResourcePicker(options) {
|
|
|
5486
5546
|
};
|
|
5487
5547
|
}
|
|
5488
5548
|
|
|
5549
|
+
// src/renderer/hooks/useWindowDragLock.ts
|
|
5550
|
+
var import_react13 = require("react");
|
|
5551
|
+
var DRAG_LOCK_ATTR = "data-window-drag-locked";
|
|
5552
|
+
var DRAG_LOCK_STATE_KEY = "__sanqian_window_drag_lock_state__";
|
|
5553
|
+
function hasDocument() {
|
|
5554
|
+
return typeof document !== "undefined";
|
|
5555
|
+
}
|
|
5556
|
+
function getWindowDragLockState() {
|
|
5557
|
+
const globalRef = globalThis;
|
|
5558
|
+
if (!globalRef[DRAG_LOCK_STATE_KEY]) {
|
|
5559
|
+
globalRef[DRAG_LOCK_STATE_KEY] = { count: 0 };
|
|
5560
|
+
}
|
|
5561
|
+
return globalRef[DRAG_LOCK_STATE_KEY];
|
|
5562
|
+
}
|
|
5563
|
+
function applyDragLockState() {
|
|
5564
|
+
if (!hasDocument()) return;
|
|
5565
|
+
const root = document.documentElement;
|
|
5566
|
+
if (getWindowDragLockState().count > 0) {
|
|
5567
|
+
root.setAttribute(DRAG_LOCK_ATTR, "true");
|
|
5568
|
+
} else {
|
|
5569
|
+
root.removeAttribute(DRAG_LOCK_ATTR);
|
|
5570
|
+
}
|
|
5571
|
+
}
|
|
5572
|
+
function acquireWindowDragLock() {
|
|
5573
|
+
if (!hasDocument()) return () => {
|
|
5574
|
+
};
|
|
5575
|
+
const state = getWindowDragLockState();
|
|
5576
|
+
state.count += 1;
|
|
5577
|
+
applyDragLockState();
|
|
5578
|
+
let released = false;
|
|
5579
|
+
return () => {
|
|
5580
|
+
if (released) return;
|
|
5581
|
+
released = true;
|
|
5582
|
+
state.count = Math.max(0, state.count - 1);
|
|
5583
|
+
applyDragLockState();
|
|
5584
|
+
};
|
|
5585
|
+
}
|
|
5586
|
+
function useWindowDragLock(active) {
|
|
5587
|
+
(0, import_react13.useEffect)(() => {
|
|
5588
|
+
if (!active) return;
|
|
5589
|
+
return acquireWindowDragLock();
|
|
5590
|
+
}, [active]);
|
|
5591
|
+
}
|
|
5592
|
+
|
|
5489
5593
|
// src/core/history.ts
|
|
5490
5594
|
function safeParseArgs(value) {
|
|
5491
5595
|
if (!value) return void 0;
|
|
@@ -5534,6 +5638,50 @@ function getNumericMessageId(message) {
|
|
|
5534
5638
|
}
|
|
5535
5639
|
return void 0;
|
|
5536
5640
|
}
|
|
5641
|
+
function parseAttachedResourceRef(rawRef) {
|
|
5642
|
+
const segments = rawRef.split(":");
|
|
5643
|
+
if (segments.length < 2) return null;
|
|
5644
|
+
const providerId = segments.slice(0, -1).join(":").trim();
|
|
5645
|
+
const resourceId = segments[segments.length - 1].trim();
|
|
5646
|
+
if (!providerId || !resourceId) return null;
|
|
5647
|
+
return { providerId, resourceId };
|
|
5648
|
+
}
|
|
5649
|
+
function normalizeAttachedResources(raw) {
|
|
5650
|
+
if (!Array.isArray(raw)) return void 0;
|
|
5651
|
+
const resources = [];
|
|
5652
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5653
|
+
for (const item of raw) {
|
|
5654
|
+
let providerId = "";
|
|
5655
|
+
let resourceId = "";
|
|
5656
|
+
let entry = null;
|
|
5657
|
+
if (typeof item === "string") {
|
|
5658
|
+
const parsed = parseAttachedResourceRef(item.trim());
|
|
5659
|
+
if (parsed) {
|
|
5660
|
+
providerId = parsed.providerId;
|
|
5661
|
+
resourceId = parsed.resourceId;
|
|
5662
|
+
}
|
|
5663
|
+
} else if (item && typeof item === "object") {
|
|
5664
|
+
entry = item;
|
|
5665
|
+
const providerRaw = typeof entry.providerId === "string" ? entry.providerId : typeof entry.provider_id === "string" ? entry.provider_id : "";
|
|
5666
|
+
const resourceRaw = typeof entry.resourceId === "string" ? entry.resourceId : typeof entry.resource_id === "string" ? entry.resource_id : "";
|
|
5667
|
+
providerId = providerRaw.trim();
|
|
5668
|
+
resourceId = resourceRaw.trim();
|
|
5669
|
+
}
|
|
5670
|
+
if (!providerId || !resourceId) continue;
|
|
5671
|
+
const dedupeKey = `${providerId}\0${resourceId}`;
|
|
5672
|
+
if (seen.has(dedupeKey)) continue;
|
|
5673
|
+
seen.add(dedupeKey);
|
|
5674
|
+
resources.push({
|
|
5675
|
+
providerId,
|
|
5676
|
+
resourceId,
|
|
5677
|
+
title: entry && typeof entry.title === "string" && entry.title.trim().length > 0 ? entry.title.trim() : resourceId,
|
|
5678
|
+
summary: entry && typeof entry.summary === "string" && entry.summary.trim().length > 0 ? entry.summary.trim() : void 0,
|
|
5679
|
+
type: entry && typeof entry.type === "string" && entry.type.trim().length > 0 ? entry.type.trim() : void 0,
|
|
5680
|
+
icon: entry && typeof entry.icon === "string" && entry.icon.trim().length > 0 ? entry.icon.trim() : void 0
|
|
5681
|
+
});
|
|
5682
|
+
}
|
|
5683
|
+
return resources.length > 0 ? resources : void 0;
|
|
5684
|
+
}
|
|
5537
5685
|
function mergeConsecutiveAssistantMessages(rawMessages) {
|
|
5538
5686
|
const result = [];
|
|
5539
5687
|
let i = 0;
|
|
@@ -5703,7 +5851,8 @@ function mergeConsecutiveAssistantMessages(rawMessages) {
|
|
|
5703
5851
|
timestamp: msg.timestamp || msg.created_at || (/* @__PURE__ */ new Date()).toISOString(),
|
|
5704
5852
|
toolCalls: parseToolCalls(msg.toolCalls || msg.tool_calls),
|
|
5705
5853
|
thinking: msg.thinking || void 0,
|
|
5706
|
-
filePaths: msg.filePaths
|
|
5854
|
+
filePaths: msg.filePaths,
|
|
5855
|
+
attachedResources: normalizeAttachedResources(msg.attachedResources || msg.attached_resources)
|
|
5707
5856
|
});
|
|
5708
5857
|
i++;
|
|
5709
5858
|
}
|
|
@@ -6387,38 +6536,38 @@ function createSdkAdapter(config) {
|
|
|
6387
6536
|
var import_browser = require("@yushaw/sanqian-sdk/browser");
|
|
6388
6537
|
|
|
6389
6538
|
// src/renderer/components/MessageList.tsx
|
|
6390
|
-
var
|
|
6539
|
+
var import_react14 = require("react");
|
|
6391
6540
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
6392
6541
|
var SCROLL_THRESHOLD = 100;
|
|
6393
|
-
var MessageList = (0,
|
|
6542
|
+
var MessageList = (0, import_react14.memo)(function MessageList2({
|
|
6394
6543
|
messages,
|
|
6395
6544
|
className = "",
|
|
6396
6545
|
renderMessage,
|
|
6397
6546
|
autoScroll = true,
|
|
6398
6547
|
scrollBehavior = "smooth"
|
|
6399
6548
|
}) {
|
|
6400
|
-
const containerRef = (0,
|
|
6401
|
-
const isNearBottomRef = (0,
|
|
6402
|
-
const checkIfNearBottom = (0,
|
|
6549
|
+
const containerRef = (0, import_react14.useRef)(null);
|
|
6550
|
+
const isNearBottomRef = (0, import_react14.useRef)(true);
|
|
6551
|
+
const checkIfNearBottom = (0, import_react14.useCallback)(() => {
|
|
6403
6552
|
const container = containerRef.current;
|
|
6404
6553
|
if (!container) return true;
|
|
6405
6554
|
return container.scrollTop <= SCROLL_THRESHOLD;
|
|
6406
6555
|
}, []);
|
|
6407
|
-
const handleScroll = (0,
|
|
6556
|
+
const handleScroll = (0, import_react14.useCallback)(() => {
|
|
6408
6557
|
isNearBottomRef.current = checkIfNearBottom();
|
|
6409
6558
|
}, [checkIfNearBottom]);
|
|
6410
|
-
const scrollToBottom = (0,
|
|
6559
|
+
const scrollToBottom = (0, import_react14.useCallback)(
|
|
6411
6560
|
(behavior = scrollBehavior) => {
|
|
6412
6561
|
containerRef.current?.scrollTo({ top: 0, behavior });
|
|
6413
6562
|
},
|
|
6414
6563
|
[scrollBehavior]
|
|
6415
6564
|
);
|
|
6416
|
-
(0,
|
|
6565
|
+
(0, import_react14.useEffect)(() => {
|
|
6417
6566
|
if (autoScroll && isNearBottomRef.current) {
|
|
6418
6567
|
scrollToBottom();
|
|
6419
6568
|
}
|
|
6420
6569
|
}, [messages, autoScroll, scrollToBottom]);
|
|
6421
|
-
(0,
|
|
6570
|
+
(0, import_react14.useEffect)(() => {
|
|
6422
6571
|
scrollToBottom("instant");
|
|
6423
6572
|
isNearBottomRef.current = true;
|
|
6424
6573
|
}, [scrollToBottom]);
|
|
@@ -6436,9 +6585,9 @@ var MessageList = (0, import_react13.memo)(function MessageList2({
|
|
|
6436
6585
|
});
|
|
6437
6586
|
|
|
6438
6587
|
// src/renderer/components/MessageBubble.tsx
|
|
6439
|
-
var
|
|
6588
|
+
var import_react15 = require("react");
|
|
6440
6589
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
6441
|
-
var MessageBubble = (0,
|
|
6590
|
+
var MessageBubble = (0, import_react15.memo)(function MessageBubble2({
|
|
6442
6591
|
message,
|
|
6443
6592
|
className = "",
|
|
6444
6593
|
children,
|
|
@@ -6446,29 +6595,26 @@ var MessageBubble = (0, import_react14.memo)(function MessageBubble2({
|
|
|
6446
6595
|
}) {
|
|
6447
6596
|
const isStreaming = message.isStreaming ?? false;
|
|
6448
6597
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className, "data-role": message.role, "data-streaming": isStreaming, children: [
|
|
6449
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "message-content", children: renderContent ? renderContent(message.content, isStreaming) : /* @__PURE__ */ (0, import_jsx_runtime4.
|
|
6450
|
-
message.content,
|
|
6451
|
-
isStreaming && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "streaming-cursor", children: "\u258C" })
|
|
6452
|
-
] }) }),
|
|
6598
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "message-content", children: renderContent ? renderContent(message.content, isStreaming) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children: message.content }) }),
|
|
6453
6599
|
children
|
|
6454
6600
|
] });
|
|
6455
6601
|
});
|
|
6456
6602
|
|
|
6457
6603
|
// src/renderer/components/SanqianChat.tsx
|
|
6458
|
-
var
|
|
6604
|
+
var import_react29 = require("react");
|
|
6459
6605
|
|
|
6460
6606
|
// src/renderer/utils/chatConfig.ts
|
|
6461
|
-
var
|
|
6607
|
+
var import_react16 = require("react");
|
|
6462
6608
|
var getSystemTheme = () => {
|
|
6463
6609
|
if (typeof window === "undefined") return "light";
|
|
6464
6610
|
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
6465
6611
|
};
|
|
6466
6612
|
function useResolvedTheme(mode = "auto") {
|
|
6467
|
-
const [resolvedTheme, setResolvedTheme] = (0,
|
|
6613
|
+
const [resolvedTheme, setResolvedTheme] = (0, import_react16.useState)(() => {
|
|
6468
6614
|
if (mode === "auto") return getSystemTheme();
|
|
6469
6615
|
return mode === "dark" ? "dark" : "light";
|
|
6470
6616
|
});
|
|
6471
|
-
(0,
|
|
6617
|
+
(0, import_react16.useEffect)(() => {
|
|
6472
6618
|
if (mode !== "auto") {
|
|
6473
6619
|
setResolvedTheme(mode === "dark" ? "dark" : "light");
|
|
6474
6620
|
return;
|
|
@@ -6530,7 +6676,7 @@ function getBaseColors(isDark) {
|
|
|
6530
6676
|
};
|
|
6531
6677
|
}
|
|
6532
6678
|
function useAccentStyle(accentColor) {
|
|
6533
|
-
return (0,
|
|
6679
|
+
return (0, import_react16.useMemo)(() => {
|
|
6534
6680
|
if (!accentColor) return void 0;
|
|
6535
6681
|
const rgb = parseColorToRgb(accentColor);
|
|
6536
6682
|
if (!rgb) {
|
|
@@ -6572,7 +6718,7 @@ function resolveOnPin(onPin) {
|
|
|
6572
6718
|
}
|
|
6573
6719
|
|
|
6574
6720
|
// src/renderer/utils/useChatHeader.tsx
|
|
6575
|
-
var
|
|
6721
|
+
var import_react17 = require("react");
|
|
6576
6722
|
|
|
6577
6723
|
// src/renderer/assets/sanqianLogo.ts
|
|
6578
6724
|
var SANQIAN_LOGO_DATA_URI = "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyBpZD0iTGF5ZXJfMiIgZGF0YS1uYW1lPSJMYXllciAyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MTUuODcgNDI4LjIiPgogIDxnIGlkPSJMYXllcl8xLTIiIGRhdGEtbmFtZT0iTGF5ZXIgMSI+CiAgICA8ZyBpZD0iQzhvaUxXIj4KICAgICAgPGc+CiAgICAgICAgPHBhdGggZD0iTTQwNC45LDE1OC4wM2wxLjk4LTEuMDFjLS4zMSw2LjM1LDEuMDQsMTIuNTYsMS43NCwxOC44Mi41Myw0LjcyLDEuNjIsOC41NywxLjI2LDE0LjY4LTEuMDcsMTguNDEtNy4wOCwzNS45Ni0xMS45OCw1My41bDcuOTUtMTYuNTRjMy43MS0xMi4wOCw2Ljc4LTI0LjI0LDguMDUtMzYuODdsMS45Ny0uMWMtMS43MSw0LjkxLTEuNDQsMTAuNjYtMi4yNiwxNS43NC00LjY3LDI5LjA1LTE3LjgzLDU4LjI3LTM1LjMxLDgxLjY5LTguNzYsMTEuNzMtMTkuNzgsMjEuMzUtMjguNDQsMzIuNTYtMi45OSwzLjg4LTEyLjM4LDcuOTktMTYuMjMsMTAuNTUtMi4wOCwxLjM4LTQuOTQsNS44Ny02LjQ4LDcuMDEtNiw0LjQ1LTE3LjE5LDUuNDMtMjIuMjYsMTEuNDcsMS4xLDEuMTksMy42OS0uNTQsNC45NS0xLjA1LDE1LjQ0LTYuMiwyOC45NC0xMy45Niw0Mi42MS0yMy40LDQuNjMsMS4wNi0uODQsMi4zMS0xLjg5LDMuMDgtNDEuOTYsMzAuNTUtOTAuNDYsNDYuMy0xNDEuOTQsMjcuNjQtMTkuMzEtNy0yNi4yMS0xOC45Ny00MC41NS0yNi40NS0xMy4xLTYuODMtMTUuOTktMTEuNTctMjUuMTgtMjIuNTQtMi45My0zLjUtMTAuNzEtMTEuNDctMTIuNDItMTQuODYtLjU2LTEuMTEtNi4yLTIwLjQ4LTYuMjEtMjEuNi0uMDQtNC4zNSwzLjE0LTkuOTcsMy42My0xNC44NC44LTcuOTMtMi45Ny0xOC45MSwzLTI0LjQ5LjY3LDMuMTQuNzgsNi41NSwxLjkxLDkuNjEuNTEsMS4zNy0uMzYsMS43LDIuMDksMS40LDEuOTQtNC4yNi0uMzYtOS45OS4xNy0xMy4yNSwxLjIxLTcuNDcsOC4zLTIxLjg0LDEzLjMzLTI3Ljc2LDUuMzUtNi4yOSwxNC4xMy0xNC4wOSwyMi41MS0xNC40OWwtMTAsOS40OSw2Ljk5LTEuNWMtMy4wNCw0LjgxLTcuNDUsOC43My0xMC40MSwxMy41OS01LjA2LDguMjktNS44NiwxNy44MS02LjU5LDI3LjQzbDQuMDIsMTkuNDljMi4wOC0uOTQuNTUtNS4wNSwxLjItNy4yOS4yNC0uODMsMi4yNi0zLjA5LDIuNzgtMi43LDMuMiwxNC4wNiwxMC40NSwyNC41NSwyMC40MiwzNC42MSwyNS4xLDI1LjM1LDY0LjA0LDMyLjc4LDk3LjI3LDE5LjU2LDguMDMtMy4xOSwxNS43LTguOTYsMjMuMzItMTIuMTdsLTIsMi45OGgxLjQ5YzE3LjE1LTEyLjY2LDMzLjYzLTI3LjExLDQyLjUzLTQ2Ljk5bDIsLjUxLS4wMyw1LjQ4LDguMy0xNi4yLDkuNy0yNy43OWMuNDUsNy41OS0yLjYxLDE0LjY3LTQuNDQsMjEuODYtLjkyLDMuNjItLjQ1LDUuNzgtMi4zOSwxMC44LTYuNTksMTcuMDgtMTkuMTgsMzMuMzEtMzIuMTYsNDUuODVsMy45OC0uNTFjLS4wMy40Ny4xNywxLjA1LDAsMS40OS0xLjg3LDQuNzItMjQuMzMsMjAuMTQtMjkuNzEsMjMuMy0xMC4zMSw2LjA1LTIxLjY3LDExLjEtMzMuMjcsMTQuMjMtLjE2LDEuODUsMy4yNi45OCw0LjM3Ljg2LDM2LjgtNC4wMiw3NS4yOC0yOS43NCw5NS40NS02MC41NSwxMS40MS0xNy40MywxNi42Ni0zMy4yNCwyMS44Ny01My4xMy44OC0zLjM2LDMuMzUtNi4wOSwyLjMyLTEwLjE5LDEuNjctLjI2LDEuMDcsMi40MSwxLjA0LDMuNTMtLjA5LDIuODUtLjkyLDUuMjMtMS4wOSw3LjkzLS4wNywxLjA4LS42NCwzLjc5LDEuMDMsMy41Mmw0Ljk2LTE5LjU0YzEuNTYtMTcuMzEsMy41NC0zMi4yOS43NS00OS42Ni0xLjAxLTYuMy00LjA2LTEzLjMyLTQuNzItMTkuMy0uMjQtMi4xNy40LTIuNjQsMS4yNS0uMjQuNzcsMi4xNywxLjE5LDQuNTIsMS43Nyw2Ljc1LDEuNzEuMjcsMS4wNy0yLjQuOTEtMy40LS42LTMuNTctMy4xLTEwLjk4LTQuNDQtMTQuNTctMy43OS0xMC4yMS0xMC4zMS0xOS42My0xMy40Ny0zMC4wMSwxLjU0Ljk1LDMuMTksMy43MSw0LjE5LDUuMywxMy4xMywyMC45OCwyMC42OSw0NC4zMiwyNC44Miw2OC43WiIvPgogICAgICAgIDxnPgogICAgICAgICAgPHBhdGggZD0iTTIyMC44OSw0MDYuMDJjLS4yNiwxLjMzLDEuODMsMS42LDIuNzQsMS43NSwzMi4xLDUuMjksNTguMjgsMS41MSw4OC4yNC0xMS4yNmwyOS4wMS0xNS40OGMtNC43Nyw1LjEyLTEyLjEyLDkuNjQtMTguMzMsMTMuMTYtNy4wNCwzLjk5LTE5LjI3LDcuNzItMjQuNjgsMTEuMzItLjQxLjI3LTEuMzIsMS4yNC0uOTksMS41aDUuOTljLTYuNjcsMS40Ny0xMy40OCw0LjgzLTE5Ljk3LDYuNTQtNS4xMywxLjM1LTE3LjY2LDIuMzctMjEuMDQsMy45Ni0uNDYuMjEtMS4yNiwxLjMtLjk4LDEuNTFsNC45OSwxYy0yOC4zLDUuNTktNTcuMTQtLjQ4LTg0LjQ4LTguMDEtMS42LDEuMDUuNzUsMS4xOCwxLjQ1LDEuNTMsMTMuMzMsNi42OSwyOS4yMiwxMC4wNyw0NC4wNCwxMS40OWwtMS4wMSwxLjk4LDUsLjAyYy4yNSwxLjcyLTIuMzcsMS4wNi0zLjQ4Ljk4LTMxLjc4LTIuNDEtNjcuMzktMTYuNTMtOTMuNDMtMzQuNTgtMTcuNDYtMTIuMS0zMS4xNS0yNy4wMy00NS41NC00MS40NWwtMjAuNTMtMzEuOTYtMSwzLjk5Yy0uMTItLjcxLTEuOTktOS4yNC00LjAxLTYuOTguNjksMi43NSwyLjYzLDUuNDQsMy41NCw3Ljk1LjM0Ljk0LDEuMzIsMy4yNS0uNTMsMy4wMy0xMC42OC0yMS44NS0xNy44My00NS45NS0xOS4wNS03MC40NS0uNDItOC40OSwzLjMtNDEuNCw4LjE2LTQ3LjQyLjE3LS4yMSwzLjA2LDEuMTgsMy44Ny0yLjY1bC0xLjk4LS40N2MtLjg1LTUuMDQsMy42NC02LjUyLDUuNjYtOS44MnM5LjM3LTE2LjcsMTAuMzEtMTkuNzFjLjE2LS41MS4yNy0xLjYzLS40OC0xLjQ4LTIuNzUsMi4xOC0zLjgzLDUuNTktNS42Niw4LjM0LS42OCwxLjAyLTIuMDIsMy4xMi0xLjgzLjE4LDExLjc1LTI0LjQ3LDI4LjEzLTQyLjQxLDUwLjY1LTU3LjM1LDUuOTYtMy45NSwxMi44Mi02LjUsMTguMzMtMTEuMTYtOS43My41LTIyLjE4LDQuMzItMzAuOTksOC41LTMuMywxLjU3LTguNTIsNi4wOC0xMS4wNyw2Ljk2LTEuNjQuNTctMy4wOC0uNi01LjIxLjUtMS44LjkzLTEwLjY0LDguNi0xMi43NCwxMC41MS0yNC43OSwyMi41Ni00MS4yNiw1Ny41MS00Niw5MC41MS0xLjYxLjA1LTIuMDUtMy41My0yLjA0LTQuNTMuMDUtNC4wOSwxLjMtMTAuMjksMi4wNS0xNC40NmwtMy44OS4xYy0yLjIsMTEuOTYtNS43OSwyMy41OC01LjEyLDM1Ljg4bC0yLTYuOTljLTEuNDctLjA5LTEuNzYsMy41OS0xLjg3LDQuNjEtMi40NywyMy44NSw2LjI4LDU4LjIxLDE1LjQsODAuMzYsMS4wMiwyLjQ5LDkuMTQsMTcuMjEsOC40OCwxOC4wMS0xLjU5LDEuOTItMi4xNC0xLjQ5LTIuNDctMS45OS0xMy4zNC0yMC4yMi0yMS42Mi00My4xLTI1LjU0LTY3LjAxbC0xLjk4LDEuMDFjLTIuMzYtMTUuMTEtNC45NS0yOS4wNy00LjA1LTQ0LjU0LjMyLTUuNDQsMi42Mi0xMC44NywyLjAzLTE2LjQ2bC0zLjk4LDE2LjUxYy0uOTUsMTAuMzEtLjU5LDIwLjY4LTEuMDEsMzEtLjA1LDEuMjEuNzYsMy43Mi0uOTksMy40OC0yLjAxLTE4LjI0LS41NC0zNi4zMSwzLjI4LTU0LjIsNS42OS0yNi42LDE4LjI4LTU0LjI3LDM2LjE5LTc0LjgxLDEyLjUzLTE0LjM3LDI4LjEyLTI3Ljk5LDQyLjg4LTM4LjY4LDIuMDktMS41MSw1LjA0LTMuOCw3LjMxLTUuMTMsOC4xLTQuNzIsMTcuODQtNS45OSwyNS4zMS0xMS42OC0uNTgtMS4xMS0zLjA2LS4zNi00LjA2LS4wNi00LjkzLDEuNDUtMTIuMTUsNC4wNy0xNi45Miw2LjA4LTUuOTIsMi41LTExLjU0LDUuNzEtMTcsOS4wNmwtMy4wMS0xLjU2YzcuMzEtMy4yNywxMy41My03LjI4LDIxLjAzLTEwLjQ4LDQxLjYzLTE3LjcyLDEwNS4zMi0yMCwxMzcuMzYsMTYuNTMsNy40NSw4LjQ5LDE5LjI1LDIyLjU4LDI1LjA1LDMwLjk5LDEuODgsMi43MiwyLjc5LDUuNzQsMS41NSw4Ljk0aDMuMDJjLS41OC45NC0uOTksNi41Ni0uOCw2Ljg0LjQ0LjY1LDIuOTcuNjQsMy4zOCwyLjY0LjI5LDEuNDMsMS40OSwxNC43LDEuNDMsMTUuOTUtLjAzLjYtMS44MS40Ny0yLjAxLDEuMjUtLjg0LDMuMjcuNDcsMTIuNTEtLjA3LDE2LjY4LS45NSw3LjM0LTYuMTksMTAuMTItOS44MywxNS4yNy0xLjI4LDEuODEtMS45OCw2LjU3LTQuMTUsNy44NC0xLjc3LDEuMDQtNC45NS42NC03LjE4LDEuNjEtMi4zNCwxLjAyLTMuNTEsNi42Ni03Ljc4LDQuOTNsMi45OS0xMWMtMy4zOSw0LjA2LTEzLjU2LDEwLjAzLTEwLjIxLjI4LDEuMzEtMy44MS44NC0zLjI4LDEuNTEtNi41NC44MS0zLjkyLDMuNzktMTIuOTIsMy43MS0xNi4xNi0uMDEtLjQyLTEuOTktLjk4LTIuNy0yLjM2LTQuMDItNy44Mi02LjM1LTE1LjE3LTEyLjY2LTIxLjg3LTExLjMtMTItNDIuMzMtMTguMi01Ny44OS0xNC4xLTE2Ljg4LDQuNDUtNDQuNjUsMjYuNDQtNTEuMyw0Mi43LTgsMTkuNTgtMTUuMTcsMzkuNjctMTIuMyw2MS4zOCw0LjA5LDMwLjg2LDE2LjE2LDUzLjYsMzMuNCw3OC42LDEuNTMsMi4yMiw0LjIxLDMuNTksNS40NCw2LjA1LTMuNzktMS4zNy03Ljc1LTUuOTQtMTAuNTEtOC45OC0xMC45My0xMS45OS0xOS44OS0yNi4yNS0yNi41LTQxLjAxLTMuMDMsMS40LDMuMjksNi43Mi0uOTcsNy45OWwtNy4wMy0xNy45OS0xLjk4LDEuOTljLS40Mi0yLjYtMS4wOC04LjIzLTQuMDItOC40OCw0LjMsMjguMjgsMTIuOTgsNTIuNjYsMzEuMDQsNzQuOTYsMjcuNDgsMzMuOTQsNzIuOTMsNjEuMzIsMTE3LjM1LDYyLjY1bDguNjIsMS44OGgtMjFaIi8+CiAgICAgICAgICA8cGF0aCBkPSJNMjg4LjQ4LDQxLjQzYzE3LDEzLjA0LDI2LjQ2LDI0LjkxLDM2LjU4LDQzLjkyLDE1Ljc5LDI5LjY4LDIyLjc5LDYyLjM3LDE1LjgyLDk1LjY3LTEuNjcuMjYtMS4wOS0yLjQzLTEuMDMtMy41My4yLTMuNDksMS42NC02Ljg3LDEuMDMtMTAuNDdsLTEuNTEuOThjLTIuOCwyMS43Mi0xMC41OSw0NS44NC0yMy4wNSw2My45NS01LjY4LDguMjYtOS44NSwxMC41NS0xNi45NSwxNi4wNS0yLjk1LDIuMjktNi4xOSw4LjE3LTkuNDgsNy41MiwxLjA3LTEuODMsNS44NS0zLjk1LDQuNDktNi41MWwtMTAuNDksNyw4Ljk5LTguNS0xLjQ4LS40OWMtMTguNjIsMTcuMTktNDguNjUsMjkuNDYtNzMuNTEsMTkuNDQtMS42LS42NS0yLjQ1LjEtMS45OS0yLjQ1LDEzLjc2LDYuMTcsMjcuODEsMi4wMyw0MC45Ny0zLjUyLDM2LjAyLTE1LjE5LDU3LjE2LTUzLjQ4LDU2LjkyLTkyLjA5LS4wMi0zLjE5LS41Mi0xMS43LTIuODktMTMuMzksMS44OSwxMC0uMywyMi40Ny0zLjMxLDMyLjIxLS4zMiwxLjA1LS4yNiwzLjAzLTEuNjksMi43OSw5Ljc1LTUxLjA4LTIwLjUyLTEwMC41NC02My43MS0xMjUuOC02LjQ1LTMuNzctMTQuMzUtNS42Ni0xOS41Ni0xMC40OWwtMTguNzQtNi43YzIuMDktLjA3LDQuMTgtLjE0LDYuMjYuMjMsMjAuOTcsMy43NywzOS44NCwxNC4zNiw1OC40NCwyMy41NSwxLjczLjg1LDMuNDUsMS44Myw1LjA0LDIuOSwyLjgyLDEuODgsOC42OSw5LjgxLDkuNzcsMTAuMy40My4yLDEuNjQuMjUsMS40OC0uNDktMzEuNzMtMzkuNzgtODMuNTMtNTguNjMtMTMzLjk5LTUzLjUybDcuOTktMi45OGMtMTguMjUuMjEtMzcuNDcsNC40MS01NC41MiwxMC45Ny0yLjg2LjI4LS44Ny0xLjI5LjE2LTEuODUsMS4yMS0uNjUsMTQuNzItNS4xMiwxMy4zNy02LjEyLTE2LjY3LDMuNjUtMzMuMTIsMTEuNy00Ny41MiwyMC45Ny05LjE1LDUuODktMTUuODIsMTIuMTMtMjMuOTcsMTkuMDItMS4xMi45NS0xLjYzLDIuNDItMy41LDEuOTksMy42My0zLjQyLDQuMzEtNy41Myw3LjgyLTEwLjksNS40Mi01LjIyLDE2LjA3LTEzLjEzLDIyLjQ0LTE3LjM5LDMyLjA3LTIxLjQ1LDY5LjEzLTMxLjM4LDEwNy43NC0zMC43MS0uNTMtMS41NS01LjAxLTEuNzktNi41MS0xLjk4LTMuOTEtLjQ5LTEyLjY5LjQ4LTE0LjgyLjAxLS43My0uMTYtLjYtMS45Mi0xLjMzLTIuMDYtMi45OC0uNTMtMTAuNzgsMS43LTE0LjMzLDEuMDItLjI0LTEuMzcsMS43OC0xLjUxLDIuNzUtMS43Miw2LjU5LTEuNDQsMTMuOTgtMS4xLDIwLjcyLTIuMzEsMS43Ny0uMzIsMi45OSwxLjEsMi41Mi0xLjk1bC0zOC45OSwzLjk4LDE2Ljk5LTQtNC45OS0xLjk4YzUyLjEyLTcuOTIsMTA0LjI4LDcuNzMsMTQ1LjU5LDM5LjRaIi8+CiAgICAgICAgICA8cGF0aCBkPSJNODAuODksMzQ2LjAxYy00LjUyLjUxLTMuNDQtMi45NC00LjEtMy44Ni0uMTItLjE2LTEuNDMuNTMtMS45MS4yNC0zLjE0LTEuODktMy4yMi02LjEzLTMuMDEtOS4zN2wtMS45OCwxLjk5LTIuMDItMy41MWMxLjk1LS44LDIuMjktMS4yMSwyLjAxLTMuNDhsMTAuOTksMTcuOThaIi8+CiAgICAgICAgPC9nPgogICAgICA8L2c+CiAgICA8L2c+CiAgPC9nPgo8L3N2Zz4=";
|
|
@@ -6615,11 +6761,11 @@ var resolveLogoNode = (logo, size, alt = SANQIAN_LOGO_ALT) => {
|
|
|
6615
6761
|
|
|
6616
6762
|
// src/renderer/utils/useChatHeader.tsx
|
|
6617
6763
|
var useChatHeader = (config) => {
|
|
6618
|
-
const resolvedOnClose = (0,
|
|
6619
|
-
const resolvedOnPin = (0,
|
|
6620
|
-
const [isPinned, setIsPinned] = (0,
|
|
6621
|
-
const isFirstRender = (0,
|
|
6622
|
-
(0,
|
|
6764
|
+
const resolvedOnClose = (0, import_react17.useMemo)(() => resolveOnClose(config?.onClose), [config?.onClose]);
|
|
6765
|
+
const resolvedOnPin = (0, import_react17.useMemo)(() => resolveOnPin(config?.onPin), [config?.onPin]);
|
|
6766
|
+
const [isPinned, setIsPinned] = (0, import_react17.useState)(config?.alwaysOnTop ?? false);
|
|
6767
|
+
const isFirstRender = (0, import_react17.useRef)(true);
|
|
6768
|
+
(0, import_react17.useEffect)(() => {
|
|
6623
6769
|
if (isFirstRender.current) {
|
|
6624
6770
|
isFirstRender.current = false;
|
|
6625
6771
|
return;
|
|
@@ -6631,8 +6777,8 @@ var useChatHeader = (config) => {
|
|
|
6631
6777
|
}, [config?.alwaysOnTop, resolvedOnPin]);
|
|
6632
6778
|
const showPin = !!resolvedOnPin || typeof config?.alwaysOnTop === "boolean";
|
|
6633
6779
|
const showClose = !!resolvedOnClose;
|
|
6634
|
-
const logoNode = (0,
|
|
6635
|
-
const togglePin = (0,
|
|
6780
|
+
const logoNode = (0, import_react17.useMemo)(() => resolveLogoNode(config?.logo, "header"), [config?.logo]);
|
|
6781
|
+
const togglePin = (0, import_react17.useCallback)(() => {
|
|
6636
6782
|
setIsPinned((prev) => {
|
|
6637
6783
|
const nextPinned = !prev;
|
|
6638
6784
|
resolvedOnPin?.(nextPinned);
|
|
@@ -6650,14 +6796,14 @@ var useChatHeader = (config) => {
|
|
|
6650
6796
|
};
|
|
6651
6797
|
|
|
6652
6798
|
// src/renderer/components/SanqianMessageList.tsx
|
|
6653
|
-
var
|
|
6799
|
+
var import_react22 = require("react");
|
|
6654
6800
|
var import_react_virtuoso = require("react-virtuoso");
|
|
6655
6801
|
|
|
6656
6802
|
// src/renderer/components/SanqianChatMessage.tsx
|
|
6657
|
-
var
|
|
6803
|
+
var import_react21 = require("react");
|
|
6658
6804
|
|
|
6659
6805
|
// src/renderer/renderers/MarkdownRenderer.tsx
|
|
6660
|
-
var
|
|
6806
|
+
var import_react18 = require("react");
|
|
6661
6807
|
var import_streamdown = require("streamdown");
|
|
6662
6808
|
var import_rehype_harden = require("rehype-harden");
|
|
6663
6809
|
var import_remark_gfm = __toESM(require("remark-gfm"));
|
|
@@ -6671,7 +6817,7 @@ function safeParseUrl(href) {
|
|
|
6671
6817
|
return void 0;
|
|
6672
6818
|
}
|
|
6673
6819
|
}
|
|
6674
|
-
var MarkdownRenderer = (0,
|
|
6820
|
+
var MarkdownRenderer = (0, import_react18.memo)(function MarkdownRenderer2({
|
|
6675
6821
|
content,
|
|
6676
6822
|
isStreaming = false,
|
|
6677
6823
|
className = "",
|
|
@@ -6679,11 +6825,11 @@ var MarkdownRenderer = (0, import_react17.memo)(function MarkdownRenderer2({
|
|
|
6679
6825
|
onLinkClick,
|
|
6680
6826
|
linkHandler
|
|
6681
6827
|
}) {
|
|
6682
|
-
const allowedProtocols = (0,
|
|
6828
|
+
const allowedProtocols = (0, import_react18.useMemo)(() => {
|
|
6683
6829
|
const custom = linkHandler?.allowedProtocols || [];
|
|
6684
6830
|
return [.../* @__PURE__ */ new Set([...DEFAULT_PROTOCOLS, ...custom])];
|
|
6685
6831
|
}, [linkHandler?.allowedProtocols]);
|
|
6686
|
-
const rehypePlugins = (0,
|
|
6832
|
+
const rehypePlugins = (0, import_react18.useMemo)(() => {
|
|
6687
6833
|
const origin = typeof window !== "undefined" ? window.location.origin : "http://localhost";
|
|
6688
6834
|
return [
|
|
6689
6835
|
[import_rehype_harden.harden, {
|
|
@@ -6697,7 +6843,7 @@ var MarkdownRenderer = (0, import_react17.memo)(function MarkdownRenderer2({
|
|
|
6697
6843
|
import_streamdown.defaultRehypePlugins.katex
|
|
6698
6844
|
];
|
|
6699
6845
|
}, [allowedProtocols]);
|
|
6700
|
-
const handleLinkClick = (0,
|
|
6846
|
+
const handleLinkClick = (0, import_react18.useCallback)((href, event) => {
|
|
6701
6847
|
if (linkHandler?.onLinkClick) {
|
|
6702
6848
|
const linkEvent = {
|
|
6703
6849
|
href,
|
|
@@ -6715,19 +6861,12 @@ var MarkdownRenderer = (0, import_react17.memo)(function MarkdownRenderer2({
|
|
|
6715
6861
|
onLinkClick(href, event);
|
|
6716
6862
|
}
|
|
6717
6863
|
}, [linkHandler, onLinkClick]);
|
|
6718
|
-
const remarkPlugins = (0,
|
|
6864
|
+
const remarkPlugins = (0, import_react18.useMemo)(() => {
|
|
6719
6865
|
return [import_remark_gfm.default, import_streamdown.defaultRemarkPlugins.math];
|
|
6720
6866
|
}, []);
|
|
6721
|
-
const customComponents = (0,
|
|
6867
|
+
const customComponents = (0, import_react18.useMemo)(() => {
|
|
6722
6868
|
const comps = {};
|
|
6723
6869
|
comps.p = ({ children }) => {
|
|
6724
|
-
if (isStreaming && children && typeof children === "string" && children.endsWith("\u258C")) {
|
|
6725
|
-
const textWithoutCursor = children.slice(0, -1);
|
|
6726
|
-
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("p", { children: [
|
|
6727
|
-
textWithoutCursor,
|
|
6728
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: { color: "var(--chat-accent)" }, className: "chat-cursor-breathing", children: "\u258C" })
|
|
6729
|
-
] });
|
|
6730
|
-
}
|
|
6731
6870
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { children });
|
|
6732
6871
|
};
|
|
6733
6872
|
const hasLinkHandler = onLinkClick || linkHandler?.onLinkClick || components?.a;
|
|
@@ -6770,15 +6909,27 @@ var MarkdownRenderer = (0, import_react17.memo)(function MarkdownRenderer2({
|
|
|
6770
6909
|
}
|
|
6771
6910
|
return comps;
|
|
6772
6911
|
}, [components, isStreaming, handleLinkClick, onLinkClick, linkHandler]);
|
|
6773
|
-
const displayContent = isStreaming ? content.replace(/\n+$/, "")
|
|
6774
|
-
|
|
6912
|
+
const displayContent = isStreaming ? content.replace(/\n+$/, "") : content;
|
|
6913
|
+
const streamClassName = isStreaming ? "chat-streaming-cursor" : void 0;
|
|
6914
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: `${PROSE_CLASSES}${className ? ` ${className}` : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
6915
|
+
import_streamdown.Streamdown,
|
|
6916
|
+
{
|
|
6917
|
+
remarkPlugins,
|
|
6918
|
+
rehypePlugins,
|
|
6919
|
+
components: customComponents,
|
|
6920
|
+
mode: isStreaming ? "streaming" : "static",
|
|
6921
|
+
isAnimating: isStreaming,
|
|
6922
|
+
className: streamClassName,
|
|
6923
|
+
children: displayContent
|
|
6924
|
+
}
|
|
6925
|
+
) });
|
|
6775
6926
|
});
|
|
6776
6927
|
|
|
6777
6928
|
// src/renderer/components/IntermediateSteps.tsx
|
|
6778
|
-
var
|
|
6929
|
+
var import_react20 = require("react");
|
|
6779
6930
|
|
|
6780
6931
|
// src/renderer/renderers/ToolArgumentsDisplay.tsx
|
|
6781
|
-
var
|
|
6932
|
+
var import_react19 = require("react");
|
|
6782
6933
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
6783
6934
|
function formatValue(value, indent = 0) {
|
|
6784
6935
|
const indentStr = " ".repeat(indent);
|
|
@@ -6838,7 +6989,7 @@ function formatValue(value, indent = 0) {
|
|
|
6838
6989
|
}
|
|
6839
6990
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-[var(--chat-text)]", children: String(value) });
|
|
6840
6991
|
}
|
|
6841
|
-
var ToolArgumentsDisplay = (0,
|
|
6992
|
+
var ToolArgumentsDisplay = (0, import_react19.memo)(function ToolArgumentsDisplay2({
|
|
6842
6993
|
args,
|
|
6843
6994
|
className = ""
|
|
6844
6995
|
}) {
|
|
@@ -6904,7 +7055,7 @@ function ExpandableText({
|
|
|
6904
7055
|
style,
|
|
6905
7056
|
maxLines = 3
|
|
6906
7057
|
}) {
|
|
6907
|
-
const [isExpanded, setIsExpanded] = (0,
|
|
7058
|
+
const [isExpanded, setIsExpanded] = (0, import_react20.useState)(false);
|
|
6908
7059
|
const trimmed = content.trim();
|
|
6909
7060
|
const lines = trimmed.split("\n");
|
|
6910
7061
|
const needsExpand = lines.length > maxLines;
|
|
@@ -6925,7 +7076,7 @@ function ExpandableText({
|
|
|
6925
7076
|
);
|
|
6926
7077
|
}
|
|
6927
7078
|
function ToolCallItem({ toolCall, toolResult }) {
|
|
6928
|
-
const [expanded, setExpanded] = (0,
|
|
7079
|
+
const [expanded, setExpanded] = (0, import_react20.useState)(false);
|
|
6929
7080
|
const hasArgs = toolCall.toolArgs && Object.keys(toolCall.toolArgs).length > 0;
|
|
6930
7081
|
const rawName = cleanToolName(toolCall.toolName);
|
|
6931
7082
|
const displayName = rawName && !/^[{[]/.test(rawName.trim()) ? rawName : toolCall.toolCallId || "tool";
|
|
@@ -6963,7 +7114,7 @@ function StreamingToolCallItem({
|
|
|
6963
7114
|
isActive,
|
|
6964
7115
|
strings
|
|
6965
7116
|
}) {
|
|
6966
|
-
const [expanded, setExpanded] = (0,
|
|
7117
|
+
const [expanded, setExpanded] = (0, import_react20.useState)(false);
|
|
6967
7118
|
const hasArgs = toolCall.toolArgs && Object.keys(toolCall.toolArgs).length > 0;
|
|
6968
7119
|
const rawName = cleanToolName(toolCall.toolName);
|
|
6969
7120
|
const displayName = rawName && !/^[{[]/.test(rawName.trim()) ? rawName : toolCall.toolCallId || "tool";
|
|
@@ -7031,7 +7182,7 @@ function groupBlocksImpl(blocks) {
|
|
|
7031
7182
|
}
|
|
7032
7183
|
return rounds;
|
|
7033
7184
|
}
|
|
7034
|
-
var ThinkingSection = (0,
|
|
7185
|
+
var ThinkingSection = (0, import_react20.memo)(function ThinkingSection2({
|
|
7035
7186
|
thinking,
|
|
7036
7187
|
currentThinking,
|
|
7037
7188
|
isStreaming,
|
|
@@ -7040,16 +7191,16 @@ var ThinkingSection = (0, import_react19.memo)(function ThinkingSection2({
|
|
|
7040
7191
|
className = "",
|
|
7041
7192
|
strings = {}
|
|
7042
7193
|
}) {
|
|
7043
|
-
const contentRef = (0,
|
|
7044
|
-
const isUserScrollingRef = (0,
|
|
7045
|
-
const [loadingSymbolIndex, setLoadingSymbolIndex] = (0,
|
|
7046
|
-
const [manualExpanded, setManualExpanded] = (0,
|
|
7194
|
+
const contentRef = (0, import_react20.useRef)(null);
|
|
7195
|
+
const isUserScrollingRef = (0, import_react20.useRef)(false);
|
|
7196
|
+
const [loadingSymbolIndex, setLoadingSymbolIndex] = (0, import_react20.useState)(0);
|
|
7197
|
+
const [manualExpanded, setManualExpanded] = (0, import_react20.useState)(false);
|
|
7047
7198
|
const effectiveIsStreaming = isComplete ? false : isStreaming;
|
|
7048
7199
|
const effectiveIsPaused = isComplete ? false : isPaused;
|
|
7049
7200
|
const isExpanded = effectiveIsStreaming || effectiveIsPaused || manualExpanded;
|
|
7050
7201
|
const displayContent = effectiveIsStreaming || effectiveIsPaused ? currentThinking || thinking : thinking;
|
|
7051
7202
|
const hasContent = displayContent && displayContent.split("\n").filter((line) => line.trim() && !line.trim().match(/^─+$/)).length > 0;
|
|
7052
|
-
(0,
|
|
7203
|
+
(0, import_react20.useEffect)(() => {
|
|
7053
7204
|
if (effectiveIsStreaming) {
|
|
7054
7205
|
const interval = setInterval(() => {
|
|
7055
7206
|
setLoadingSymbolIndex((prev) => (prev + 1) % LOADING_SYMBOLS.length);
|
|
@@ -7057,13 +7208,13 @@ var ThinkingSection = (0, import_react19.memo)(function ThinkingSection2({
|
|
|
7057
7208
|
return () => clearInterval(interval);
|
|
7058
7209
|
}
|
|
7059
7210
|
}, [effectiveIsStreaming]);
|
|
7060
|
-
(0,
|
|
7211
|
+
(0, import_react20.useEffect)(() => {
|
|
7061
7212
|
if (effectiveIsStreaming && isExpanded && contentRef.current && !isUserScrollingRef.current) {
|
|
7062
7213
|
contentRef.current.scrollTop = contentRef.current.scrollHeight;
|
|
7063
7214
|
}
|
|
7064
7215
|
}, [displayContent, effectiveIsStreaming, isExpanded]);
|
|
7065
|
-
const prevManualExpandedRef = (0,
|
|
7066
|
-
(0,
|
|
7216
|
+
const prevManualExpandedRef = (0, import_react20.useRef)(manualExpanded);
|
|
7217
|
+
(0, import_react20.useEffect)(() => {
|
|
7067
7218
|
const wasCollapsed = !prevManualExpandedRef.current;
|
|
7068
7219
|
const isNowExpanded = manualExpanded;
|
|
7069
7220
|
if (wasCollapsed && isNowExpanded && !effectiveIsStreaming && contentRef.current) {
|
|
@@ -7071,13 +7222,13 @@ var ThinkingSection = (0, import_react19.memo)(function ThinkingSection2({
|
|
|
7071
7222
|
}
|
|
7072
7223
|
prevManualExpandedRef.current = manualExpanded;
|
|
7073
7224
|
}, [manualExpanded, effectiveIsStreaming]);
|
|
7074
|
-
const handleScroll = (0,
|
|
7225
|
+
const handleScroll = (0, import_react20.useCallback)(() => {
|
|
7075
7226
|
if (!contentRef.current || !effectiveIsStreaming) return;
|
|
7076
7227
|
const { scrollTop, scrollHeight, clientHeight } = contentRef.current;
|
|
7077
7228
|
const isAtBottom = scrollHeight - scrollTop - clientHeight < 20;
|
|
7078
7229
|
isUserScrollingRef.current = !isAtBottom;
|
|
7079
7230
|
}, [effectiveIsStreaming]);
|
|
7080
|
-
(0,
|
|
7231
|
+
(0, import_react20.useEffect)(() => {
|
|
7081
7232
|
if (!effectiveIsStreaming) {
|
|
7082
7233
|
isUserScrollingRef.current = false;
|
|
7083
7234
|
}
|
|
@@ -7116,14 +7267,14 @@ var ThinkingSection = (0, import_react19.memo)(function ThinkingSection2({
|
|
|
7116
7267
|
isExpanded && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { ref: contentRef, onScroll: handleScroll, className: "mt-1.5 ml-2 max-h-60 overflow-y-auto", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("pre", { className: "whitespace-pre-wrap m-0 font-sans italic", style: { color: "var(--chat-text)", opacity: 0.7, fontSize: "0.8125rem", lineHeight: "1.3" }, children: displayContent?.trim() }) })
|
|
7117
7268
|
] });
|
|
7118
7269
|
});
|
|
7119
|
-
var IntermediateSteps = (0,
|
|
7270
|
+
var IntermediateSteps = (0, import_react20.memo)(function IntermediateSteps2({
|
|
7120
7271
|
blocks,
|
|
7121
7272
|
className = "",
|
|
7122
7273
|
defaultExpanded = false,
|
|
7123
7274
|
strings = {}
|
|
7124
7275
|
}) {
|
|
7125
|
-
const [isExpanded, setIsExpanded] = (0,
|
|
7126
|
-
const rounds = (0,
|
|
7276
|
+
const [isExpanded, setIsExpanded] = (0, import_react20.useState)(defaultExpanded);
|
|
7277
|
+
const rounds = (0, import_react20.useMemo)(() => groupBlocksIntoRounds(blocks), [blocks]);
|
|
7127
7278
|
if (rounds.length === 0) return null;
|
|
7128
7279
|
const stepCount = rounds.filter((round) => round.toolCalls.length > 0).length;
|
|
7129
7280
|
if (stepCount === 0) return null;
|
|
@@ -7205,7 +7356,7 @@ var IntermediateSteps = (0, import_react19.memo)(function IntermediateSteps2({
|
|
|
7205
7356
|
}) })
|
|
7206
7357
|
] });
|
|
7207
7358
|
});
|
|
7208
|
-
var StreamingTimeline = (0,
|
|
7359
|
+
var StreamingTimeline = (0, import_react20.memo)(function StreamingTimeline2({
|
|
7209
7360
|
blocks,
|
|
7210
7361
|
currentThinking = "",
|
|
7211
7362
|
isThinkingStreaming = false,
|
|
@@ -7214,14 +7365,14 @@ var StreamingTimeline = (0, import_react19.memo)(function StreamingTimeline2({
|
|
|
7214
7365
|
className = "",
|
|
7215
7366
|
strings = {}
|
|
7216
7367
|
}) {
|
|
7217
|
-
const [isExpanded, setIsExpanded] = (0,
|
|
7218
|
-
const isUserScrollingRef = (0,
|
|
7219
|
-
const timelineRef = (0,
|
|
7368
|
+
const [isExpanded, setIsExpanded] = (0, import_react20.useState)(true);
|
|
7369
|
+
const isUserScrollingRef = (0, import_react20.useRef)(false);
|
|
7370
|
+
const timelineRef = (0, import_react20.useRef)(null);
|
|
7220
7371
|
const isThinkingActive = isThinkingStreaming;
|
|
7221
7372
|
const isToolsActive = isToolCallsStreaming;
|
|
7222
|
-
const rounds = (0,
|
|
7373
|
+
const rounds = (0, import_react20.useMemo)(() => groupAllBlocksIntoRounds(blocks), [blocks]);
|
|
7223
7374
|
const activeThinking = currentThinking;
|
|
7224
|
-
const displayRounds = (0,
|
|
7375
|
+
const displayRounds = (0, import_react20.useMemo)(() => {
|
|
7225
7376
|
const result = [];
|
|
7226
7377
|
for (let roundIdx = 0; roundIdx < rounds.length; roundIdx++) {
|
|
7227
7378
|
const round = rounds[roundIdx];
|
|
@@ -7283,18 +7434,18 @@ var StreamingTimeline = (0, import_react19.memo)(function StreamingTimeline2({
|
|
|
7283
7434
|
}, [rounds, activeThinking, isThinkingActive, isToolsActive]);
|
|
7284
7435
|
const stepCount = rounds.filter((round) => round.toolCalls.length > 0).length;
|
|
7285
7436
|
const summary = `${stepCount} ${strings.steps || "\u6B65"}`;
|
|
7286
|
-
const handleScroll = (0,
|
|
7437
|
+
const handleScroll = (0, import_react20.useCallback)(() => {
|
|
7287
7438
|
if (!timelineRef.current) return;
|
|
7288
7439
|
const { scrollTop, scrollHeight, clientHeight } = timelineRef.current;
|
|
7289
7440
|
const isAtBottom = scrollHeight - scrollTop - clientHeight < 20;
|
|
7290
7441
|
isUserScrollingRef.current = !isAtBottom;
|
|
7291
7442
|
}, []);
|
|
7292
|
-
(0,
|
|
7443
|
+
(0, import_react20.useEffect)(() => {
|
|
7293
7444
|
if (isExpanded && timelineRef.current && !isUserScrollingRef.current) {
|
|
7294
7445
|
timelineRef.current.scrollTop = timelineRef.current.scrollHeight;
|
|
7295
7446
|
}
|
|
7296
7447
|
}, [displayRounds, isExpanded]);
|
|
7297
|
-
(0,
|
|
7448
|
+
(0, import_react20.useEffect)(() => {
|
|
7298
7449
|
if (!isThinkingActive && !isToolsActive) {
|
|
7299
7450
|
isUserScrollingRef.current = false;
|
|
7300
7451
|
}
|
|
@@ -7380,27 +7531,101 @@ var StreamingTimeline = (0, import_react19.memo)(function StreamingTimeline2({
|
|
|
7380
7531
|
] });
|
|
7381
7532
|
});
|
|
7382
7533
|
|
|
7383
|
-
// src/renderer/
|
|
7384
|
-
|
|
7385
|
-
|
|
7386
|
-
if (
|
|
7534
|
+
// src/renderer/utils/intermediateDisplay.ts
|
|
7535
|
+
function normalizeToolResult(result) {
|
|
7536
|
+
if (result === void 0 || result === null) return void 0;
|
|
7537
|
+
if (typeof result === "string") {
|
|
7538
|
+
return result.trim() ? result : void 0;
|
|
7539
|
+
}
|
|
7540
|
+
try {
|
|
7541
|
+
return JSON.stringify(result, null, 2);
|
|
7542
|
+
} catch {
|
|
7543
|
+
return String(result);
|
|
7544
|
+
}
|
|
7545
|
+
}
|
|
7546
|
+
function buildFallbackBlocksFromToolCalls(toolCalls) {
|
|
7547
|
+
if (!toolCalls || toolCalls.length === 0) return void 0;
|
|
7548
|
+
const blocks = [];
|
|
7549
|
+
let timestamp = Date.now();
|
|
7550
|
+
for (const toolCall of toolCalls) {
|
|
7551
|
+
const toolStatus = toolCall.status || (toolCall.result !== void 0 ? "completed" : "running");
|
|
7552
|
+
blocks.push({
|
|
7553
|
+
type: "tool_call",
|
|
7554
|
+
content: "",
|
|
7555
|
+
timestamp: timestamp++,
|
|
7556
|
+
toolName: toolCall.name,
|
|
7557
|
+
toolArgs: toolCall.args,
|
|
7558
|
+
toolCallId: toolCall.id,
|
|
7559
|
+
toolStatus,
|
|
7560
|
+
isIntermediate: true
|
|
7561
|
+
});
|
|
7562
|
+
const resultContent = normalizeToolResult(toolCall.result);
|
|
7563
|
+
if (resultContent) {
|
|
7564
|
+
blocks.push({
|
|
7565
|
+
type: "tool_result",
|
|
7566
|
+
content: resultContent,
|
|
7567
|
+
timestamp: timestamp++,
|
|
7568
|
+
toolName: toolCall.name,
|
|
7569
|
+
toolCallId: toolCall.id,
|
|
7570
|
+
isIntermediate: true
|
|
7571
|
+
});
|
|
7572
|
+
}
|
|
7573
|
+
}
|
|
7574
|
+
return blocks.length > 0 ? blocks : void 0;
|
|
7575
|
+
}
|
|
7576
|
+
function getAssistantDisplayState(message) {
|
|
7387
7577
|
const isUser = message.role === "user";
|
|
7388
|
-
const
|
|
7389
|
-
const
|
|
7578
|
+
const displayBlocks = message.blocks && message.blocks.length > 0 ? message.blocks : buildFallbackBlocksFromToolCalls(message.toolCalls);
|
|
7579
|
+
const hasToolCalls = Boolean(message.toolCalls && message.toolCalls.length > 0);
|
|
7580
|
+
const hasToolBlocks = Boolean(
|
|
7581
|
+
displayBlocks && displayBlocks.some((block) => block.type === "tool_call" || block.type === "tool_result")
|
|
7582
|
+
);
|
|
7390
7583
|
const hasToolActivity = hasToolCalls || hasToolBlocks;
|
|
7391
|
-
const
|
|
7392
|
-
|
|
7393
|
-
|
|
7584
|
+
const hasRunningToolCalls = Boolean(
|
|
7585
|
+
message.toolCalls?.some((tool) => tool.status === "running") || displayBlocks?.some((block) => block.type === "tool_call" && block.toolStatus === "running")
|
|
7586
|
+
);
|
|
7587
|
+
const isEffectivelyComplete = Boolean(
|
|
7588
|
+
message.isComplete || !message.isStreaming && !message.isThinkingStreaming && !message.isToolCallsStreaming && !hasRunningToolCalls
|
|
7589
|
+
);
|
|
7590
|
+
const hasIntermediateBlocks = Boolean(displayBlocks?.some((block) => block.isIntermediate));
|
|
7394
7591
|
const hasThinking = Boolean(message.thinking || message.isThinkingStreaming || message.currentThinking);
|
|
7592
|
+
const showIntermediateSteps = Boolean(
|
|
7593
|
+
!isUser && isEffectivelyComplete && hasToolActivity && hasIntermediateBlocks
|
|
7594
|
+
);
|
|
7595
|
+
const showStreamingTimeline = Boolean(!isUser && !showIntermediateSteps && hasToolActivity);
|
|
7395
7596
|
const showThinkingSection = Boolean(!isUser && !hasToolActivity && !showIntermediateSteps && hasThinking);
|
|
7396
|
-
|
|
7397
|
-
|
|
7597
|
+
return {
|
|
7598
|
+
displayBlocks,
|
|
7599
|
+
hasToolActivity,
|
|
7600
|
+
isEffectivelyComplete,
|
|
7601
|
+
showIntermediateSteps,
|
|
7602
|
+
showStreamingTimeline,
|
|
7603
|
+
showThinkingSection
|
|
7604
|
+
};
|
|
7605
|
+
}
|
|
7606
|
+
|
|
7607
|
+
// src/renderer/components/SanqianChatMessage.tsx
|
|
7608
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
7609
|
+
var SanqianChatMessage = (0, import_react21.memo)(function SanqianChatMessage2({ message }) {
|
|
7610
|
+
if (message.role === "tool") return null;
|
|
7611
|
+
const isUser = message.role === "user";
|
|
7612
|
+
const {
|
|
7613
|
+
displayBlocks,
|
|
7614
|
+
isEffectivelyComplete,
|
|
7615
|
+
showIntermediateSteps,
|
|
7616
|
+
showStreamingTimeline,
|
|
7617
|
+
showThinkingSection
|
|
7618
|
+
} = getAssistantDisplayState(message);
|
|
7619
|
+
const isToolCallsStreaming = (message.isToolCallsStreaming ?? (message.toolCalls?.some((tc) => tc.status === "running") ?? false)) || (displayBlocks?.some((b) => b.type === "tool_call" && b.toolStatus === "running") ?? false);
|
|
7620
|
+
const isThinkingPaused = message.isThinkingPaused ?? Boolean(!message.isThinkingStreaming && message.currentThinking && !isEffectivelyComplete);
|
|
7398
7621
|
const showStreamingPlaceholder = Boolean(
|
|
7399
7622
|
!isUser && message.isStreaming && !message.content && !showStreamingTimeline && !showIntermediateSteps
|
|
7400
7623
|
);
|
|
7401
7624
|
const hasAttachedResources = isUser && message.attachedResources && message.attachedResources.length > 0;
|
|
7625
|
+
const hasUserText = isUser && message.content.trim().length > 0;
|
|
7626
|
+
const shouldRenderBubble = !isUser || hasUserText;
|
|
7402
7627
|
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: `flex ${isUser ? "justify-end" : "justify-start"} mb-4`, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: `text-left ${isUser ? "max-w-[80%]" : "w-full"}`, children: [
|
|
7403
|
-
!isUser && showIntermediateSteps &&
|
|
7628
|
+
!isUser && showIntermediateSteps && displayBlocks && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IntermediateSteps, { blocks: displayBlocks }),
|
|
7404
7629
|
showThinkingSection && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
7405
7630
|
ThinkingSection,
|
|
7406
7631
|
{
|
|
@@ -7408,21 +7633,21 @@ var SanqianChatMessage = (0, import_react20.memo)(function SanqianChatMessage2({
|
|
|
7408
7633
|
currentThinking: message.currentThinking,
|
|
7409
7634
|
isStreaming: message.isThinkingStreaming,
|
|
7410
7635
|
isPaused: isThinkingPaused,
|
|
7411
|
-
isComplete:
|
|
7636
|
+
isComplete: isEffectivelyComplete
|
|
7412
7637
|
}
|
|
7413
7638
|
),
|
|
7414
|
-
showStreamingTimeline &&
|
|
7639
|
+
showStreamingTimeline && displayBlocks && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
7415
7640
|
StreamingTimeline,
|
|
7416
7641
|
{
|
|
7417
|
-
blocks:
|
|
7642
|
+
blocks: displayBlocks,
|
|
7418
7643
|
currentThinking: message.currentThinking,
|
|
7419
7644
|
isThinkingStreaming: message.isThinkingStreaming,
|
|
7420
7645
|
isToolCallsStreaming,
|
|
7421
|
-
isComplete:
|
|
7646
|
+
isComplete: isEffectivelyComplete
|
|
7422
7647
|
}
|
|
7423
7648
|
),
|
|
7424
7649
|
hasAttachedResources && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(MessageAttachedResources, { resources: message.attachedResources }),
|
|
7425
|
-
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: `relative group ${isUser ? "inline-block max-w-full" : "block w-full"}`, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
7650
|
+
shouldRenderBubble && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: `relative group ${isUser ? "inline-block max-w-full" : "block w-full"}`, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
7426
7651
|
"div",
|
|
7427
7652
|
{
|
|
7428
7653
|
className: `message-bubble-wrapper ${isUser ? "rounded-2xl shadow-sm bg-[var(--chat-accent)] text-white px-4 py-3 whitespace-pre-wrap break-words" : "text-[var(--chat-text)] break-words"}`,
|
|
@@ -7438,7 +7663,7 @@ var SanqianChatMessage = (0, import_react20.memo)(function SanqianChatMessage2({
|
|
|
7438
7663
|
) })
|
|
7439
7664
|
] }) });
|
|
7440
7665
|
});
|
|
7441
|
-
var MessageAttachedResources = (0,
|
|
7666
|
+
var MessageAttachedResources = (0, import_react21.memo)(function MessageAttachedResources2({
|
|
7442
7667
|
resources
|
|
7443
7668
|
}) {
|
|
7444
7669
|
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "flex flex-wrap gap-1.5 mb-2 justify-end", children: resources.map((resource, index) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
@@ -7460,9 +7685,9 @@ var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
|
7460
7685
|
var AT_BOTTOM_THRESHOLD = 50;
|
|
7461
7686
|
var INCREASE_VIEWPORT_BY = { top: 1500, bottom: 1500 };
|
|
7462
7687
|
function ResizeAwareMessage({ message, onHeightChange }) {
|
|
7463
|
-
const containerRef = (0,
|
|
7464
|
-
const prevHeightRef = (0,
|
|
7465
|
-
(0,
|
|
7688
|
+
const containerRef = (0, import_react22.useRef)(null);
|
|
7689
|
+
const prevHeightRef = (0, import_react22.useRef)(0);
|
|
7690
|
+
(0, import_react22.useEffect)(() => {
|
|
7466
7691
|
const container = containerRef.current;
|
|
7467
7692
|
if (!container || !onHeightChange) return;
|
|
7468
7693
|
let rafId = null;
|
|
@@ -7484,16 +7709,16 @@ function ResizeAwareMessage({ message, onHeightChange }) {
|
|
|
7484
7709
|
}, [onHeightChange]);
|
|
7485
7710
|
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { ref: containerRef, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(SanqianChatMessage, { message }) });
|
|
7486
7711
|
}
|
|
7487
|
-
var SanqianMessageList = (0,
|
|
7712
|
+
var SanqianMessageList = (0, import_react22.forwardRef)(
|
|
7488
7713
|
function SanqianMessageList2({ messages, isLoading, className = "", emptyState, onClickEmpty, onAtBottomChange }, ref) {
|
|
7489
|
-
const virtuosoRef = (0,
|
|
7490
|
-
const [, setAtBottomState] = (0,
|
|
7491
|
-
const atBottomRef = (0,
|
|
7492
|
-
const isManualScrollingRef = (0,
|
|
7493
|
-
const manualScrollTimeoutRef = (0,
|
|
7494
|
-
const isFollowOutputScrollingRef = (0,
|
|
7495
|
-
const followOutputScrollTimeoutRef = (0,
|
|
7496
|
-
const setAtBottom = (0,
|
|
7714
|
+
const virtuosoRef = (0, import_react22.useRef)(null);
|
|
7715
|
+
const [, setAtBottomState] = (0, import_react22.useState)(true);
|
|
7716
|
+
const atBottomRef = (0, import_react22.useRef)(true);
|
|
7717
|
+
const isManualScrollingRef = (0, import_react22.useRef)(false);
|
|
7718
|
+
const manualScrollTimeoutRef = (0, import_react22.useRef)(null);
|
|
7719
|
+
const isFollowOutputScrollingRef = (0, import_react22.useRef)(false);
|
|
7720
|
+
const followOutputScrollTimeoutRef = (0, import_react22.useRef)(null);
|
|
7721
|
+
const setAtBottom = (0, import_react22.useCallback)(
|
|
7497
7722
|
(value) => {
|
|
7498
7723
|
if (isManualScrollingRef.current) return;
|
|
7499
7724
|
if (isFollowOutputScrollingRef.current && !value) return;
|
|
@@ -7503,18 +7728,18 @@ var SanqianMessageList = (0, import_react21.forwardRef)(
|
|
|
7503
7728
|
},
|
|
7504
7729
|
[onAtBottomChange]
|
|
7505
7730
|
);
|
|
7506
|
-
const visibleMessages = (0,
|
|
7731
|
+
const visibleMessages = (0, import_react22.useMemo)(
|
|
7507
7732
|
() => messages.filter((message) => message.role !== "tool"),
|
|
7508
7733
|
[messages]
|
|
7509
7734
|
);
|
|
7510
7735
|
const lastMessage = visibleMessages.length > 0 ? visibleMessages[visibleMessages.length - 1] : null;
|
|
7511
7736
|
const hasStreamingActivity = isLoading || (lastMessage?.isStreaming ?? false);
|
|
7512
|
-
const allItems = (0,
|
|
7737
|
+
const allItems = (0, import_react22.useMemo)(() => {
|
|
7513
7738
|
const items = [...visibleMessages];
|
|
7514
7739
|
items.push({ id: "footer-spacer", type: "footer" });
|
|
7515
7740
|
return items;
|
|
7516
7741
|
}, [visibleMessages]);
|
|
7517
|
-
const scrollToBottom = (0,
|
|
7742
|
+
const scrollToBottom = (0, import_react22.useCallback)(
|
|
7518
7743
|
(behavior = "smooth", source) => {
|
|
7519
7744
|
if (!virtuosoRef.current || allItems.length === 0) return;
|
|
7520
7745
|
const isManualScroll = source === "scroll-button";
|
|
@@ -7540,14 +7765,14 @@ var SanqianMessageList = (0, import_react21.forwardRef)(
|
|
|
7540
7765
|
},
|
|
7541
7766
|
[allItems.length, onAtBottomChange]
|
|
7542
7767
|
);
|
|
7543
|
-
(0,
|
|
7768
|
+
(0, import_react22.useImperativeHandle)(
|
|
7544
7769
|
ref,
|
|
7545
7770
|
() => ({
|
|
7546
7771
|
scrollToBottom
|
|
7547
7772
|
}),
|
|
7548
7773
|
[scrollToBottom]
|
|
7549
7774
|
);
|
|
7550
|
-
(0,
|
|
7775
|
+
(0, import_react22.useEffect)(() => {
|
|
7551
7776
|
return () => {
|
|
7552
7777
|
if (manualScrollTimeoutRef.current) {
|
|
7553
7778
|
clearTimeout(manualScrollTimeoutRef.current);
|
|
@@ -7557,13 +7782,13 @@ var SanqianMessageList = (0, import_react21.forwardRef)(
|
|
|
7557
7782
|
}
|
|
7558
7783
|
};
|
|
7559
7784
|
}, []);
|
|
7560
|
-
const handleMessageHeightChange = (0,
|
|
7785
|
+
const handleMessageHeightChange = (0, import_react22.useCallback)(() => {
|
|
7561
7786
|
if (isManualScrollingRef.current) return;
|
|
7562
7787
|
if (atBottomRef.current && hasStreamingActivity) {
|
|
7563
7788
|
scrollToBottom("auto", "height-change");
|
|
7564
7789
|
}
|
|
7565
7790
|
}, [scrollToBottom, hasStreamingActivity]);
|
|
7566
|
-
const handleClick = (0,
|
|
7791
|
+
const handleClick = (0, import_react22.useCallback)(
|
|
7567
7792
|
(e) => {
|
|
7568
7793
|
const selection = window.getSelection();
|
|
7569
7794
|
if (!selection || selection.isCollapsed) {
|
|
@@ -7574,7 +7799,7 @@ var SanqianMessageList = (0, import_react21.forwardRef)(
|
|
|
7574
7799
|
},
|
|
7575
7800
|
[onClickEmpty]
|
|
7576
7801
|
);
|
|
7577
|
-
const handleFollowOutput = (0,
|
|
7802
|
+
const handleFollowOutput = (0, import_react22.useCallback)((isAtBottom) => {
|
|
7578
7803
|
if (isAtBottom) {
|
|
7579
7804
|
if (followOutputScrollTimeoutRef.current) {
|
|
7580
7805
|
clearTimeout(followOutputScrollTimeoutRef.current);
|
|
@@ -7588,7 +7813,7 @@ var SanqianMessageList = (0, import_react21.forwardRef)(
|
|
|
7588
7813
|
}
|
|
7589
7814
|
return false;
|
|
7590
7815
|
}, []);
|
|
7591
|
-
const itemContent = (0,
|
|
7816
|
+
const itemContent = (0, import_react22.useCallback)(
|
|
7592
7817
|
(_index, item) => {
|
|
7593
7818
|
if ("type" in item && item.type === "footer") {
|
|
7594
7819
|
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "h-28" });
|
|
@@ -7622,16 +7847,17 @@ var SanqianMessageList = (0, import_react21.forwardRef)(
|
|
|
7622
7847
|
);
|
|
7623
7848
|
|
|
7624
7849
|
// src/renderer/components/ChatInput.tsx
|
|
7625
|
-
var
|
|
7850
|
+
var import_react23 = require("react");
|
|
7626
7851
|
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
7627
|
-
var ChatInput = (0,
|
|
7628
|
-
(0,
|
|
7852
|
+
var ChatInput = (0, import_react23.memo)(
|
|
7853
|
+
(0, import_react23.forwardRef)(function ChatInput2({
|
|
7629
7854
|
onSend,
|
|
7630
7855
|
onStop,
|
|
7631
7856
|
placeholder = "Type a message...",
|
|
7632
7857
|
disabled = false,
|
|
7633
7858
|
isStreaming = false,
|
|
7634
7859
|
isLoading = false,
|
|
7860
|
+
allowEmptySubmit = false,
|
|
7635
7861
|
sendLabel = "Send",
|
|
7636
7862
|
stopLabel = "Stop",
|
|
7637
7863
|
autoFocus = false,
|
|
@@ -7640,12 +7866,13 @@ var ChatInput = (0, import_react22.memo)(
|
|
|
7640
7866
|
className = "",
|
|
7641
7867
|
style
|
|
7642
7868
|
}, ref) {
|
|
7643
|
-
const [text, setText] = (0,
|
|
7644
|
-
const textareaRef = (0,
|
|
7645
|
-
const
|
|
7869
|
+
const [text, setText] = (0, import_react23.useState)("");
|
|
7870
|
+
const textareaRef = (0, import_react23.useRef)(null);
|
|
7871
|
+
const submitInFlightRef = (0, import_react23.useRef)(false);
|
|
7872
|
+
const canSend = (text.trim().length > 0 || allowEmptySubmit) && !disabled && !isLoading;
|
|
7646
7873
|
const showStopButton = isStreaming && !!onStop;
|
|
7647
7874
|
const showSpinner = isLoading && !showStopButton;
|
|
7648
|
-
(0,
|
|
7875
|
+
(0, import_react23.useImperativeHandle)(
|
|
7649
7876
|
ref,
|
|
7650
7877
|
() => ({
|
|
7651
7878
|
focus: () => textareaRef.current?.focus(),
|
|
@@ -7655,26 +7882,35 @@ var ChatInput = (0, import_react22.memo)(
|
|
|
7655
7882
|
}),
|
|
7656
7883
|
[text]
|
|
7657
7884
|
);
|
|
7658
|
-
(0,
|
|
7885
|
+
(0, import_react23.useEffect)(() => {
|
|
7659
7886
|
if (autoFocus) {
|
|
7660
7887
|
const timer = setTimeout(() => textareaRef.current?.focus(), 100);
|
|
7661
7888
|
return () => clearTimeout(timer);
|
|
7662
7889
|
}
|
|
7663
7890
|
}, [autoFocus]);
|
|
7664
|
-
const handleSubmit = (0,
|
|
7665
|
-
(e) => {
|
|
7891
|
+
const handleSubmit = (0, import_react23.useCallback)(
|
|
7892
|
+
async (e) => {
|
|
7666
7893
|
e?.preventDefault();
|
|
7667
7894
|
if (!canSend) return;
|
|
7668
|
-
|
|
7669
|
-
|
|
7895
|
+
if (submitInFlightRef.current) return;
|
|
7896
|
+
submitInFlightRef.current = true;
|
|
7897
|
+
try {
|
|
7898
|
+
const result = await onSend(text.trim());
|
|
7899
|
+
if (result !== false) {
|
|
7900
|
+
setText("");
|
|
7901
|
+
}
|
|
7902
|
+
} catch {
|
|
7903
|
+
} finally {
|
|
7904
|
+
submitInFlightRef.current = false;
|
|
7905
|
+
}
|
|
7670
7906
|
},
|
|
7671
7907
|
[text, canSend, onSend]
|
|
7672
7908
|
);
|
|
7673
|
-
const handleKeyDown = (0,
|
|
7909
|
+
const handleKeyDown = (0, import_react23.useCallback)(
|
|
7674
7910
|
(e) => {
|
|
7675
7911
|
if (e.key === "Enter" && !e.shiftKey && !e.nativeEvent.isComposing) {
|
|
7676
7912
|
e.preventDefault();
|
|
7677
|
-
handleSubmit();
|
|
7913
|
+
void handleSubmit();
|
|
7678
7914
|
}
|
|
7679
7915
|
if (e.key === "Escape" && showStopButton) {
|
|
7680
7916
|
e.preventDefault();
|
|
@@ -7685,60 +7921,70 @@ var ChatInput = (0, import_react22.memo)(
|
|
|
7685
7921
|
);
|
|
7686
7922
|
const leftPadding = leftSlot ? "2rem" : "0.75rem";
|
|
7687
7923
|
const rightPadding = rightSlot ? "2.5rem" : "0.75rem";
|
|
7688
|
-
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
7689
|
-
|
|
7690
|
-
|
|
7691
|
-
|
|
7692
|
-
|
|
7693
|
-
|
|
7694
|
-
|
|
7695
|
-
|
|
7696
|
-
|
|
7697
|
-
|
|
7698
|
-
|
|
7699
|
-
|
|
7700
|
-
|
|
7701
|
-
|
|
7702
|
-
|
|
7703
|
-
|
|
7704
|
-
|
|
7705
|
-
|
|
7706
|
-
|
|
7707
|
-
|
|
7708
|
-
|
|
7709
|
-
|
|
7710
|
-
|
|
7711
|
-
|
|
7712
|
-
|
|
7713
|
-
|
|
7714
|
-
|
|
7715
|
-
|
|
7716
|
-
|
|
7717
|
-
|
|
7718
|
-
|
|
7719
|
-
|
|
7720
|
-
|
|
7721
|
-
|
|
7722
|
-
|
|
7723
|
-
|
|
7724
|
-
|
|
7725
|
-
|
|
7726
|
-
|
|
7727
|
-
|
|
7728
|
-
|
|
7729
|
-
|
|
7730
|
-
|
|
7731
|
-
|
|
7732
|
-
|
|
7733
|
-
|
|
7734
|
-
|
|
7735
|
-
|
|
7736
|
-
|
|
7924
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
7925
|
+
"form",
|
|
7926
|
+
{
|
|
7927
|
+
onSubmit: (e) => {
|
|
7928
|
+
void handleSubmit(e);
|
|
7929
|
+
},
|
|
7930
|
+
className: `chat-input-form${className ? ` ${className}` : ""}`,
|
|
7931
|
+
style,
|
|
7932
|
+
children: [
|
|
7933
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "chat-input-box", children: [
|
|
7934
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
7935
|
+
"div",
|
|
7936
|
+
{
|
|
7937
|
+
className: "chat-input-replica",
|
|
7938
|
+
style: { paddingLeft: leftPadding, paddingRight: rightPadding },
|
|
7939
|
+
"aria-hidden": "true",
|
|
7940
|
+
children: text + " "
|
|
7941
|
+
}
|
|
7942
|
+
),
|
|
7943
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
7944
|
+
"textarea",
|
|
7945
|
+
{
|
|
7946
|
+
ref: textareaRef,
|
|
7947
|
+
value: text,
|
|
7948
|
+
onChange: (e) => setText(e.target.value),
|
|
7949
|
+
onKeyDown: handleKeyDown,
|
|
7950
|
+
placeholder,
|
|
7951
|
+
disabled,
|
|
7952
|
+
rows: 1,
|
|
7953
|
+
className: "chat-input-textarea",
|
|
7954
|
+
style: { paddingLeft: leftPadding, paddingRight: rightPadding }
|
|
7955
|
+
}
|
|
7956
|
+
),
|
|
7957
|
+
leftSlot && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "chat-input-left-slot", children: leftSlot }),
|
|
7958
|
+
rightSlot && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "chat-input-right-slot", children: rightSlot })
|
|
7959
|
+
] }),
|
|
7960
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "chat-input-send-wrapper", children: [
|
|
7961
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
7962
|
+
"button",
|
|
7963
|
+
{
|
|
7964
|
+
type: showStopButton ? "button" : "submit",
|
|
7965
|
+
onClick: showStopButton ? onStop : void 0,
|
|
7966
|
+
disabled: !showStopButton && !canSend,
|
|
7967
|
+
className: "chat-input-send-btn",
|
|
7968
|
+
"aria-label": showStopButton ? stopLabel : sendLabel,
|
|
7969
|
+
children: showSpinner ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("svg", { viewBox: "0 0 24 24", fill: "none", className: "animate-spin", children: [
|
|
7970
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("circle", { cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4", opacity: "0.25" }),
|
|
7971
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { fill: "currentColor", opacity: "0.75", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })
|
|
7972
|
+
] }) : showStopButton ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("svg", { viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("rect", { x: "6", y: "6", width: "12", height: "12", rx: "2" }) }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M4.5 10.5 12 3m0 0 7.5 7.5M12 3v18" }) })
|
|
7973
|
+
}
|
|
7974
|
+
),
|
|
7975
|
+
showStopButton && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "chat-input-stop-tooltip", role: "note", children: [
|
|
7976
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { children: stopLabel }),
|
|
7977
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "chat-input-stop-hotkey", children: "Esc" })
|
|
7978
|
+
] })
|
|
7979
|
+
] })
|
|
7980
|
+
]
|
|
7981
|
+
}
|
|
7982
|
+
);
|
|
7737
7983
|
})
|
|
7738
7984
|
);
|
|
7739
7985
|
|
|
7740
7986
|
// src/renderer/components/HitlCard.tsx
|
|
7741
|
-
var
|
|
7987
|
+
var import_react24 = require("react");
|
|
7742
7988
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
7743
7989
|
var defaultStrings = {
|
|
7744
7990
|
approve: "Approve",
|
|
@@ -7777,7 +8023,7 @@ var riskColors = {
|
|
|
7777
8023
|
icon: "!!"
|
|
7778
8024
|
}
|
|
7779
8025
|
};
|
|
7780
|
-
var HitlCard = (0,
|
|
8026
|
+
var HitlCard = (0, import_react24.memo)(function HitlCard2({
|
|
7781
8027
|
interrupt,
|
|
7782
8028
|
onApprove,
|
|
7783
8029
|
onReject,
|
|
@@ -7789,16 +8035,16 @@ var HitlCard = (0, import_react23.memo)(function HitlCard2({
|
|
|
7789
8035
|
const t = { ...defaultStrings, ...strings };
|
|
7790
8036
|
const isApproval = interrupt.type === "approval_request";
|
|
7791
8037
|
const isUserInput = interrupt.type === "user_input_request";
|
|
7792
|
-
const [answer, setAnswer] = (0,
|
|
7793
|
-
const [selectedIndices, setSelectedIndices] = (0,
|
|
7794
|
-
const [isComposing, setIsComposing] = (0,
|
|
7795
|
-
const [timeLeft, setTimeLeft] = (0,
|
|
7796
|
-
const [rememberChoice, setRememberChoice] = (0,
|
|
7797
|
-
const inputRef = (0,
|
|
7798
|
-
const textareaRef = (0,
|
|
8038
|
+
const [answer, setAnswer] = (0, import_react24.useState)(interrupt.default || "");
|
|
8039
|
+
const [selectedIndices, setSelectedIndices] = (0, import_react24.useState)([]);
|
|
8040
|
+
const [isComposing, setIsComposing] = (0, import_react24.useState)(false);
|
|
8041
|
+
const [timeLeft, setTimeLeft] = (0, import_react24.useState)(interrupt.timeout ?? null);
|
|
8042
|
+
const [rememberChoice, setRememberChoice] = (0, import_react24.useState)(false);
|
|
8043
|
+
const inputRef = (0, import_react24.useRef)(null);
|
|
8044
|
+
const textareaRef = (0, import_react24.useRef)(null);
|
|
7799
8045
|
const riskLevel = interrupt.risk_level || "medium";
|
|
7800
8046
|
const riskStyle = riskColors[riskLevel];
|
|
7801
|
-
(0,
|
|
8047
|
+
(0, import_react24.useEffect)(() => {
|
|
7802
8048
|
if (isUserInput) {
|
|
7803
8049
|
if (!interrupt.options || interrupt.options.length === 0) {
|
|
7804
8050
|
inputRef.current?.focus();
|
|
@@ -7806,7 +8052,7 @@ var HitlCard = (0, import_react23.memo)(function HitlCard2({
|
|
|
7806
8052
|
}
|
|
7807
8053
|
}
|
|
7808
8054
|
}, [isUserInput, interrupt.options]);
|
|
7809
|
-
(0,
|
|
8055
|
+
(0, import_react24.useEffect)(() => {
|
|
7810
8056
|
if (timeLeft === null || timeLeft <= 0) return;
|
|
7811
8057
|
const timer = setInterval(() => {
|
|
7812
8058
|
setTimeLeft((prev) => {
|
|
@@ -8004,12 +8250,12 @@ var HitlCard = (0, import_react23.memo)(function HitlCard2({
|
|
|
8004
8250
|
});
|
|
8005
8251
|
|
|
8006
8252
|
// src/renderer/primitives/AlertBanner.tsx
|
|
8007
|
-
var
|
|
8253
|
+
var import_react25 = require("react");
|
|
8008
8254
|
var import_jsx_runtime13 = (
|
|
8009
8255
|
// Error icon (circle with X)
|
|
8010
8256
|
require("react/jsx-runtime")
|
|
8011
8257
|
);
|
|
8012
|
-
var AlertBanner = (0,
|
|
8258
|
+
var AlertBanner = (0, import_react25.memo)(function AlertBanner2({
|
|
8013
8259
|
type,
|
|
8014
8260
|
message,
|
|
8015
8261
|
action,
|
|
@@ -8019,7 +8265,7 @@ var AlertBanner = (0, import_react24.memo)(function AlertBanner2({
|
|
|
8019
8265
|
maxLines = 3,
|
|
8020
8266
|
strings
|
|
8021
8267
|
}) {
|
|
8022
|
-
const [isExpanded, setIsExpanded] = (0,
|
|
8268
|
+
const [isExpanded, setIsExpanded] = (0, import_react25.useState)(false);
|
|
8023
8269
|
const defaultIcon = type === "error" ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("svg", { className: "size-4 shrink-0", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
8024
8270
|
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("circle", { cx: "12", cy: "12", r: "10" }),
|
|
8025
8271
|
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { d: "M15 9l-6 6M9 9l6 6", strokeLinecap: "round" })
|
|
@@ -8081,10 +8327,10 @@ var AlertBanner = (0, import_react24.memo)(function AlertBanner2({
|
|
|
8081
8327
|
});
|
|
8082
8328
|
|
|
8083
8329
|
// src/renderer/components/AddResourceButton.tsx
|
|
8084
|
-
var
|
|
8330
|
+
var import_react27 = require("react");
|
|
8085
8331
|
|
|
8086
8332
|
// src/renderer/components/ResourcePicker.tsx
|
|
8087
|
-
var
|
|
8333
|
+
var import_react26 = require("react");
|
|
8088
8334
|
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
8089
8335
|
var STRINGS = {
|
|
8090
8336
|
en: {
|
|
@@ -8102,7 +8348,7 @@ var STRINGS = {
|
|
|
8102
8348
|
attached: "\u5DF2\u6DFB\u52A0"
|
|
8103
8349
|
}
|
|
8104
8350
|
};
|
|
8105
|
-
var ResourcePicker = (0,
|
|
8351
|
+
var ResourcePicker = (0, import_react26.memo)(function ResourcePicker2({
|
|
8106
8352
|
isOpen,
|
|
8107
8353
|
onClose,
|
|
8108
8354
|
providers,
|
|
@@ -8124,14 +8370,14 @@ var ResourcePicker = (0, import_react25.memo)(function ResourcePicker2({
|
|
|
8124
8370
|
className = ""
|
|
8125
8371
|
}) {
|
|
8126
8372
|
const strings = STRINGS[locale];
|
|
8127
|
-
const pickerRef = (0,
|
|
8128
|
-
const searchInputRef = (0,
|
|
8129
|
-
const sentinelRef = (0,
|
|
8130
|
-
const listRef = (0,
|
|
8131
|
-
const scrollRestoredRef = (0,
|
|
8132
|
-
const [position, setPosition] = (0,
|
|
8373
|
+
const pickerRef = (0, import_react26.useRef)(null);
|
|
8374
|
+
const searchInputRef = (0, import_react26.useRef)(null);
|
|
8375
|
+
const sentinelRef = (0, import_react26.useRef)(null);
|
|
8376
|
+
const listRef = (0, import_react26.useRef)(null);
|
|
8377
|
+
const scrollRestoredRef = (0, import_react26.useRef)(null);
|
|
8378
|
+
const [position, setPosition] = (0, import_react26.useState)({ top: 0, left: 0, width: 280 });
|
|
8133
8379
|
const getScrollKey = (providerId) => `resource-picker-scroll-${providerId}`;
|
|
8134
|
-
(0,
|
|
8380
|
+
(0, import_react26.useEffect)(() => {
|
|
8135
8381
|
if (!isOpen || !anchorRef?.current) return;
|
|
8136
8382
|
const updatePosition = () => {
|
|
8137
8383
|
if (!anchorRef?.current) return;
|
|
@@ -8148,7 +8394,7 @@ var ResourcePicker = (0, import_react25.memo)(function ResourcePicker2({
|
|
|
8148
8394
|
window.addEventListener("resize", updatePosition);
|
|
8149
8395
|
return () => window.removeEventListener("resize", updatePosition);
|
|
8150
8396
|
}, [isOpen, anchorRef]);
|
|
8151
|
-
(0,
|
|
8397
|
+
(0, import_react26.useEffect)(() => {
|
|
8152
8398
|
if (!isOpen) return;
|
|
8153
8399
|
const handleClickOutside = (e) => {
|
|
8154
8400
|
if (pickerRef.current && !pickerRef.current.contains(e.target)) {
|
|
@@ -8161,17 +8407,17 @@ var ResourcePicker = (0, import_react25.memo)(function ResourcePicker2({
|
|
|
8161
8407
|
document.addEventListener("mousedown", handleClickOutside);
|
|
8162
8408
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
8163
8409
|
}, [isOpen, onClose, anchorRef]);
|
|
8164
|
-
(0,
|
|
8410
|
+
(0, import_react26.useEffect)(() => {
|
|
8165
8411
|
if (selectedProviderId && searchInputRef.current) {
|
|
8166
8412
|
searchInputRef.current.focus();
|
|
8167
8413
|
}
|
|
8168
8414
|
}, [selectedProviderId]);
|
|
8169
|
-
(0,
|
|
8415
|
+
(0, import_react26.useEffect)(() => {
|
|
8170
8416
|
if (isOpen) {
|
|
8171
8417
|
scrollRestoredRef.current = null;
|
|
8172
8418
|
}
|
|
8173
8419
|
}, [isOpen]);
|
|
8174
|
-
(0,
|
|
8420
|
+
(0, import_react26.useEffect)(() => {
|
|
8175
8421
|
if (!isOpen || !selectedProviderId || !listRef.current || resources.length === 0) return;
|
|
8176
8422
|
if (scrollRestoredRef.current === selectedProviderId) return;
|
|
8177
8423
|
const savedScroll = sessionStorage.getItem(getScrollKey(selectedProviderId));
|
|
@@ -8185,12 +8431,12 @@ var ResourcePicker = (0, import_react25.memo)(function ResourcePicker2({
|
|
|
8185
8431
|
}
|
|
8186
8432
|
scrollRestoredRef.current = selectedProviderId;
|
|
8187
8433
|
}, [isOpen, selectedProviderId, resources.length]);
|
|
8188
|
-
const handleListScroll = (0,
|
|
8434
|
+
const handleListScroll = (0, import_react26.useCallback)((e) => {
|
|
8189
8435
|
if (!selectedProviderId) return;
|
|
8190
8436
|
const scrollTop = e.currentTarget.scrollTop;
|
|
8191
8437
|
sessionStorage.setItem(getScrollKey(selectedProviderId), String(scrollTop));
|
|
8192
8438
|
}, [selectedProviderId]);
|
|
8193
|
-
(0,
|
|
8439
|
+
(0, import_react26.useEffect)(() => {
|
|
8194
8440
|
if (!isOpen) return;
|
|
8195
8441
|
const handleKeyDown = (e) => {
|
|
8196
8442
|
if (e.key === "Escape") {
|
|
@@ -8201,7 +8447,7 @@ var ResourcePicker = (0, import_react25.memo)(function ResourcePicker2({
|
|
|
8201
8447
|
document.addEventListener("keydown", handleKeyDown);
|
|
8202
8448
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
8203
8449
|
}, [isOpen, onClose]);
|
|
8204
|
-
(0,
|
|
8450
|
+
(0, import_react26.useEffect)(() => {
|
|
8205
8451
|
if (!sentinelRef.current || !hasMore || isLoadingResources) return;
|
|
8206
8452
|
const observer = new IntersectionObserver(
|
|
8207
8453
|
(entries) => {
|
|
@@ -8214,13 +8460,13 @@ var ResourcePicker = (0, import_react25.memo)(function ResourcePicker2({
|
|
|
8214
8460
|
observer.observe(sentinelRef.current);
|
|
8215
8461
|
return () => observer.disconnect();
|
|
8216
8462
|
}, [hasMore, isLoadingResources, onLoadMore]);
|
|
8217
|
-
const handleTabClick = (0,
|
|
8463
|
+
const handleTabClick = (0, import_react26.useCallback)((providerId) => {
|
|
8218
8464
|
if (providerId !== selectedProviderId) {
|
|
8219
8465
|
onSearchChange("");
|
|
8220
8466
|
onSelectProvider(providerId);
|
|
8221
8467
|
}
|
|
8222
8468
|
}, [selectedProviderId, onSelectProvider, onSearchChange]);
|
|
8223
|
-
const handleResourceClick = (0,
|
|
8469
|
+
const handleResourceClick = (0, import_react26.useCallback)((item) => {
|
|
8224
8470
|
onAttachResource(item);
|
|
8225
8471
|
}, [onAttachResource]);
|
|
8226
8472
|
if (!isOpen) return null;
|
|
@@ -8481,7 +8727,7 @@ var STRINGS2 = {
|
|
|
8481
8727
|
uploadImage: "\u4E0A\u4F20\u56FE\u7247"
|
|
8482
8728
|
}
|
|
8483
8729
|
};
|
|
8484
|
-
var AddResourceButton = (0,
|
|
8730
|
+
var AddResourceButton = (0, import_react27.memo)(function AddResourceButton2({
|
|
8485
8731
|
providers,
|
|
8486
8732
|
isLoadingProviders,
|
|
8487
8733
|
onUploadFile,
|
|
@@ -8502,11 +8748,11 @@ var AddResourceButton = (0, import_react26.memo)(function AddResourceButton2({
|
|
|
8502
8748
|
themeClass = ""
|
|
8503
8749
|
}) {
|
|
8504
8750
|
const strings = STRINGS2[locale];
|
|
8505
|
-
const [isMenuOpen, setIsMenuOpen] = (0,
|
|
8506
|
-
const [isPickerOpen, setIsPickerOpen] = (0,
|
|
8507
|
-
const buttonRef = (0,
|
|
8508
|
-
const menuRef = (0,
|
|
8509
|
-
(0,
|
|
8751
|
+
const [isMenuOpen, setIsMenuOpen] = (0, import_react27.useState)(false);
|
|
8752
|
+
const [isPickerOpen, setIsPickerOpen] = (0, import_react27.useState)(false);
|
|
8753
|
+
const buttonRef = (0, import_react27.useRef)(null);
|
|
8754
|
+
const menuRef = (0, import_react27.useRef)(null);
|
|
8755
|
+
(0, import_react27.useEffect)(() => {
|
|
8510
8756
|
if (!isMenuOpen) return;
|
|
8511
8757
|
const handleClickOutside = (e) => {
|
|
8512
8758
|
if (menuRef.current && !menuRef.current.contains(e.target) && buttonRef.current && !buttonRef.current.contains(e.target)) {
|
|
@@ -8516,7 +8762,7 @@ var AddResourceButton = (0, import_react26.memo)(function AddResourceButton2({
|
|
|
8516
8762
|
document.addEventListener("mousedown", handleClickOutside);
|
|
8517
8763
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
8518
8764
|
}, [isMenuOpen]);
|
|
8519
|
-
(0,
|
|
8765
|
+
(0, import_react27.useEffect)(() => {
|
|
8520
8766
|
if (!isMenuOpen) return;
|
|
8521
8767
|
const handleKeyDown = (e) => {
|
|
8522
8768
|
if (e.key === "Escape") {
|
|
@@ -8526,7 +8772,7 @@ var AddResourceButton = (0, import_react26.memo)(function AddResourceButton2({
|
|
|
8526
8772
|
document.addEventListener("keydown", handleKeyDown);
|
|
8527
8773
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
8528
8774
|
}, [isMenuOpen]);
|
|
8529
|
-
const handleButtonClick = (0,
|
|
8775
|
+
const handleButtonClick = (0, import_react27.useCallback)(() => {
|
|
8530
8776
|
if (isPickerOpen) {
|
|
8531
8777
|
setIsPickerOpen(false);
|
|
8532
8778
|
onSelectProvider(null);
|
|
@@ -8540,31 +8786,31 @@ var AddResourceButton = (0, import_react26.memo)(function AddResourceButton2({
|
|
|
8540
8786
|
}
|
|
8541
8787
|
setIsMenuOpen(!isMenuOpen);
|
|
8542
8788
|
}, [isMenuOpen, isPickerOpen, onSelectProvider, providers, onUploadFile, onUploadImage]);
|
|
8543
|
-
const handleUploadFile = (0,
|
|
8789
|
+
const handleUploadFile = (0, import_react27.useCallback)(() => {
|
|
8544
8790
|
setIsMenuOpen(false);
|
|
8545
8791
|
onUploadFile?.();
|
|
8546
8792
|
}, [onUploadFile]);
|
|
8547
|
-
const handleUploadImage = (0,
|
|
8793
|
+
const handleUploadImage = (0, import_react27.useCallback)(() => {
|
|
8548
8794
|
setIsMenuOpen(false);
|
|
8549
8795
|
onUploadImage?.();
|
|
8550
8796
|
}, [onUploadImage]);
|
|
8551
|
-
const handleProviderClick = (0,
|
|
8797
|
+
const handleProviderClick = (0, import_react27.useCallback)((providerId) => {
|
|
8552
8798
|
setIsMenuOpen(false);
|
|
8553
8799
|
onSelectProvider(providerId);
|
|
8554
8800
|
setIsPickerOpen(true);
|
|
8555
8801
|
}, [onSelectProvider]);
|
|
8556
|
-
const handlePickerClose = (0,
|
|
8802
|
+
const handlePickerClose = (0, import_react27.useCallback)(() => {
|
|
8557
8803
|
setIsPickerOpen(false);
|
|
8558
8804
|
onSelectProvider(null);
|
|
8559
8805
|
}, [onSelectProvider]);
|
|
8560
|
-
const handlePickerSelectProvider = (0,
|
|
8806
|
+
const handlePickerSelectProvider = (0, import_react27.useCallback)((providerId) => {
|
|
8561
8807
|
if (providerId === null) {
|
|
8562
8808
|
setIsPickerOpen(false);
|
|
8563
8809
|
setIsMenuOpen(true);
|
|
8564
8810
|
}
|
|
8565
8811
|
onSelectProvider(providerId);
|
|
8566
8812
|
}, [onSelectProvider]);
|
|
8567
|
-
const handleAttachResource = (0,
|
|
8813
|
+
const handleAttachResource = (0, import_react27.useCallback)((item) => {
|
|
8568
8814
|
onAttachResource(item);
|
|
8569
8815
|
setIsPickerOpen(false);
|
|
8570
8816
|
onSelectProvider(null);
|
|
@@ -8718,9 +8964,9 @@ var addResourceButtonStyles = `
|
|
|
8718
8964
|
`;
|
|
8719
8965
|
|
|
8720
8966
|
// src/renderer/components/AttachedResourceTags.tsx
|
|
8721
|
-
var
|
|
8967
|
+
var import_react28 = require("react");
|
|
8722
8968
|
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
8723
|
-
var AttachedResourceTags = (0,
|
|
8969
|
+
var AttachedResourceTags = (0, import_react28.memo)(function AttachedResourceTags2({
|
|
8724
8970
|
resources,
|
|
8725
8971
|
onRemove,
|
|
8726
8972
|
disabled
|
|
@@ -8799,7 +9045,7 @@ var attachedResourceTagsStyles = `
|
|
|
8799
9045
|
|
|
8800
9046
|
// src/renderer/components/SanqianChat.tsx
|
|
8801
9047
|
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
8802
|
-
var SanqianChat = (0,
|
|
9048
|
+
var SanqianChat = (0, import_react29.memo)(function SanqianChat2({
|
|
8803
9049
|
adapter,
|
|
8804
9050
|
placeholder,
|
|
8805
9051
|
autoConnect = true,
|
|
@@ -8811,22 +9057,22 @@ var SanqianChat = (0, import_react28.memo)(function SanqianChat2({
|
|
|
8811
9057
|
config,
|
|
8812
9058
|
logo
|
|
8813
9059
|
}) {
|
|
8814
|
-
const chatContainerRef = (0,
|
|
8815
|
-
const chatInputRef = (0,
|
|
8816
|
-
const messageListRef = (0,
|
|
8817
|
-
const onStateChangeRef = (0,
|
|
8818
|
-
(0,
|
|
9060
|
+
const chatContainerRef = (0, import_react29.useRef)(null);
|
|
9061
|
+
const chatInputRef = (0, import_react29.useRef)(null);
|
|
9062
|
+
const messageListRef = (0, import_react29.useRef)(null);
|
|
9063
|
+
const onStateChangeRef = (0, import_react29.useRef)(onStateChange);
|
|
9064
|
+
(0, import_react29.useEffect)(() => {
|
|
8819
9065
|
onStateChangeRef.current = onStateChange;
|
|
8820
9066
|
}, [onStateChange]);
|
|
8821
9067
|
const resolvedConfig = useResolvedUiConfig(config);
|
|
8822
9068
|
const { themeClass, isDarkMode } = useResolvedTheme(resolvedConfig?.theme ?? "auto");
|
|
8823
9069
|
const accentStyle = useAccentStyle(resolvedConfig?.accentColor);
|
|
8824
9070
|
const resolvedLogo = logo ?? resolvedConfig?.logo;
|
|
8825
|
-
const strings = (0,
|
|
9071
|
+
const strings = (0, import_react29.useMemo)(
|
|
8826
9072
|
() => resolveChatStrings(resolvedConfig?.locale, resolvedConfig?.strings),
|
|
8827
9073
|
[resolvedConfig?.locale, resolvedConfig?.strings]
|
|
8828
9074
|
);
|
|
8829
|
-
const headerConfig = (0,
|
|
9075
|
+
const headerConfig = (0, import_react29.useMemo)(
|
|
8830
9076
|
() => {
|
|
8831
9077
|
if (!resolvedConfig) {
|
|
8832
9078
|
return resolvedLogo ? { logo: resolvedLogo } : void 0;
|
|
@@ -8839,7 +9085,7 @@ var SanqianChat = (0, import_react28.memo)(function SanqianChat2({
|
|
|
8839
9085
|
[resolvedConfig, resolvedLogo]
|
|
8840
9086
|
);
|
|
8841
9087
|
const { logoNode, showPin, showClose, isPinned, togglePin, resolvedOnClose } = useChatHeader(headerConfig);
|
|
8842
|
-
const emptyLogoNode = (0,
|
|
9088
|
+
const emptyLogoNode = (0, import_react29.useMemo)(() => resolveLogoNode(resolvedLogo, "empty"), [resolvedLogo]);
|
|
8843
9089
|
const showHeader = !!(logoNode || showClose || showPin);
|
|
8844
9090
|
useChatStyles();
|
|
8845
9091
|
useConnection({ adapter, autoConnect });
|
|
@@ -8849,7 +9095,7 @@ var SanqianChat = (0, import_react28.memo)(function SanqianChat2({
|
|
|
8849
9095
|
onConversationChange
|
|
8850
9096
|
});
|
|
8851
9097
|
const resourcePicker = useResourcePicker({ adapter });
|
|
8852
|
-
const resourceProviders = (0,
|
|
9098
|
+
const resourceProviders = (0, import_react29.useMemo)(
|
|
8853
9099
|
() => resourcePicker.providers.filter((p) => p.hasGetList),
|
|
8854
9100
|
[resourcePicker.providers]
|
|
8855
9101
|
);
|
|
@@ -8865,13 +9111,17 @@ var SanqianChat = (0, import_react28.memo)(function SanqianChat2({
|
|
|
8865
9111
|
chat.submitHitlInput({ cancelled: true });
|
|
8866
9112
|
}
|
|
8867
9113
|
};
|
|
8868
|
-
const handleSendMessage = (0,
|
|
8869
|
-
|
|
8870
|
-
|
|
9114
|
+
const handleSendMessage = (0, import_react29.useCallback)(async (content) => {
|
|
9115
|
+
const attachedResources = resourcePicker.attachedResources.length > 0 ? [...resourcePicker.attachedResources] : void 0;
|
|
9116
|
+
const sent = await chat.trySendMessage(content, {
|
|
9117
|
+
attachedResources
|
|
8871
9118
|
});
|
|
8872
|
-
|
|
9119
|
+
if (sent) {
|
|
9120
|
+
resourcePicker.clearAttachedResources();
|
|
9121
|
+
}
|
|
9122
|
+
return sent;
|
|
8873
9123
|
}, [chat, resourcePicker]);
|
|
8874
|
-
(0,
|
|
9124
|
+
(0, import_react29.useEffect)(() => {
|
|
8875
9125
|
onStateChangeRef.current?.({
|
|
8876
9126
|
messages: chat.messages,
|
|
8877
9127
|
conversationId: chat.conversationId
|
|
@@ -8987,6 +9237,7 @@ var SanqianChat = (0, import_react28.memo)(function SanqianChat2({
|
|
|
8987
9237
|
stopLabel: strings.inputStop,
|
|
8988
9238
|
isStreaming: chat.isStreaming,
|
|
8989
9239
|
isLoading: chat.isLoading,
|
|
9240
|
+
allowEmptySubmit: resourcePicker.attachedResources.length > 0 || chat.sessionResources.length > 0,
|
|
8990
9241
|
disabled: !!chat.pendingInterrupt || chat.isLoading && !chat.isStreaming,
|
|
8991
9242
|
leftSlot: resourceProviders.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
8992
9243
|
AddResourceButton,
|
|
@@ -9017,17 +9268,17 @@ var SanqianChat = (0, import_react28.memo)(function SanqianChat2({
|
|
|
9017
9268
|
});
|
|
9018
9269
|
|
|
9019
9270
|
// src/renderer/components/FloatingChat.tsx
|
|
9020
|
-
var
|
|
9271
|
+
var import_react35 = require("react");
|
|
9021
9272
|
|
|
9022
9273
|
// src/renderer/components/ModeToggleButton.tsx
|
|
9023
|
-
var
|
|
9274
|
+
var import_react30 = require("react");
|
|
9024
9275
|
var import_jsx_runtime18 = (
|
|
9025
9276
|
// Float out icon - two overlapping panels (macOS style)
|
|
9026
9277
|
require("react/jsx-runtime")
|
|
9027
9278
|
);
|
|
9028
9279
|
function ModeToggleButton({ className, locale = "en" }) {
|
|
9029
9280
|
const { isEmbedded, toggleMode } = useChatPanel();
|
|
9030
|
-
const strings = (0,
|
|
9281
|
+
const strings = (0, import_react30.useMemo)(() => resolveChatStrings(locale), [locale]);
|
|
9031
9282
|
const handleClick = async () => {
|
|
9032
9283
|
await toggleMode();
|
|
9033
9284
|
};
|
|
@@ -9056,7 +9307,7 @@ function ModeToggleButton({ className, locale = "en" }) {
|
|
|
9056
9307
|
}
|
|
9057
9308
|
|
|
9058
9309
|
// src/renderer/components/AttachButton.tsx
|
|
9059
|
-
var
|
|
9310
|
+
var import_react31 = require("react");
|
|
9060
9311
|
var import_jsx_runtime19 = (
|
|
9061
9312
|
// Attached state: filled icon
|
|
9062
9313
|
require("react/jsx-runtime")
|
|
@@ -9064,7 +9315,7 @@ var import_jsx_runtime19 = (
|
|
|
9064
9315
|
function AttachButton({ className, locale = "en" }) {
|
|
9065
9316
|
const { isAttached, isAvailable, toggle } = useAttachState();
|
|
9066
9317
|
const { isFloating } = useChatPanel();
|
|
9067
|
-
const strings = (0,
|
|
9318
|
+
const strings = (0, import_react31.useMemo)(() => resolveChatStrings(locale), [locale]);
|
|
9068
9319
|
if (!isFloating || !isAvailable) return null;
|
|
9069
9320
|
const handleClick = async () => {
|
|
9070
9321
|
await toggle();
|
|
@@ -9094,16 +9345,16 @@ function AttachButton({ className, locale = "en" }) {
|
|
|
9094
9345
|
}
|
|
9095
9346
|
|
|
9096
9347
|
// src/renderer/components/Resizer.tsx
|
|
9097
|
-
var
|
|
9348
|
+
var import_react32 = require("react");
|
|
9098
9349
|
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
9099
9350
|
function useRafThrottle(fn) {
|
|
9100
|
-
const rafRef = (0,
|
|
9101
|
-
const argsRef = (0,
|
|
9102
|
-
const fnRef = (0,
|
|
9103
|
-
(0,
|
|
9351
|
+
const rafRef = (0, import_react32.useRef)(null);
|
|
9352
|
+
const argsRef = (0, import_react32.useRef)(null);
|
|
9353
|
+
const fnRef = (0, import_react32.useRef)(fn);
|
|
9354
|
+
(0, import_react32.useLayoutEffect)(() => {
|
|
9104
9355
|
fnRef.current = fn;
|
|
9105
9356
|
});
|
|
9106
|
-
const throttledFn = (0,
|
|
9357
|
+
const throttledFn = (0, import_react32.useCallback)((...args) => {
|
|
9107
9358
|
argsRef.current = args;
|
|
9108
9359
|
if (rafRef.current === null) {
|
|
9109
9360
|
rafRef.current = requestAnimationFrame(() => {
|
|
@@ -9114,7 +9365,7 @@ function useRafThrottle(fn) {
|
|
|
9114
9365
|
});
|
|
9115
9366
|
}
|
|
9116
9367
|
}, []);
|
|
9117
|
-
(0,
|
|
9368
|
+
(0, import_react32.useEffect)(() => {
|
|
9118
9369
|
return () => {
|
|
9119
9370
|
if (rafRef.current !== null) {
|
|
9120
9371
|
cancelAnimationFrame(rafRef.current);
|
|
@@ -9132,19 +9383,19 @@ function Resizer({
|
|
|
9132
9383
|
className = ""
|
|
9133
9384
|
}) {
|
|
9134
9385
|
const { isEmbedded, width, setWidth, onResizeEnd } = useChatPanel();
|
|
9135
|
-
const [isHovered, setIsHovered] = (0,
|
|
9136
|
-
const [isDragging, setIsDragging] = (0,
|
|
9137
|
-
const startX = (0,
|
|
9138
|
-
const startWidth = (0,
|
|
9139
|
-
const widthRef = (0,
|
|
9140
|
-
(0,
|
|
9386
|
+
const [isHovered, setIsHovered] = (0, import_react32.useState)(false);
|
|
9387
|
+
const [isDragging, setIsDragging] = (0, import_react32.useState)(false);
|
|
9388
|
+
const startX = (0, import_react32.useRef)(0);
|
|
9389
|
+
const startWidth = (0, import_react32.useRef)(0);
|
|
9390
|
+
const widthRef = (0, import_react32.useRef)(width);
|
|
9391
|
+
(0, import_react32.useLayoutEffect)(() => {
|
|
9141
9392
|
widthRef.current = width;
|
|
9142
9393
|
}, [width]);
|
|
9143
9394
|
const throttledSetWidth = useRafThrottle(setWidth);
|
|
9144
|
-
const handleDoubleClick = (0,
|
|
9395
|
+
const handleDoubleClick = (0, import_react32.useCallback)(() => {
|
|
9145
9396
|
setWidth(defaultWidth, true);
|
|
9146
9397
|
}, [defaultWidth, setWidth]);
|
|
9147
|
-
const handleMouseDown = (0,
|
|
9398
|
+
const handleMouseDown = (0, import_react32.useCallback)((e) => {
|
|
9148
9399
|
e.preventDefault();
|
|
9149
9400
|
setIsDragging(true);
|
|
9150
9401
|
startX.current = e.screenX;
|
|
@@ -9152,7 +9403,7 @@ function Resizer({
|
|
|
9152
9403
|
document.body.style.cursor = "col-resize";
|
|
9153
9404
|
document.body.style.userSelect = "none";
|
|
9154
9405
|
}, []);
|
|
9155
|
-
(0,
|
|
9406
|
+
(0, import_react32.useEffect)(() => {
|
|
9156
9407
|
if (!isDragging) return;
|
|
9157
9408
|
const handleMouseMove = (e) => {
|
|
9158
9409
|
const deltaX = e.screenX - startX.current;
|
|
@@ -9229,15 +9480,15 @@ function Resizer({
|
|
|
9229
9480
|
}
|
|
9230
9481
|
|
|
9231
9482
|
// src/renderer/components/ResourceChip.tsx
|
|
9232
|
-
var
|
|
9483
|
+
var import_react33 = require("react");
|
|
9233
9484
|
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
9234
|
-
var ResourceChip = (0,
|
|
9485
|
+
var ResourceChip = (0, import_react33.memo)(function ResourceChip2({
|
|
9235
9486
|
resource,
|
|
9236
9487
|
onRemove,
|
|
9237
9488
|
disabled,
|
|
9238
9489
|
locale: localeProp
|
|
9239
9490
|
}) {
|
|
9240
|
-
const i18nContext = (0,
|
|
9491
|
+
const i18nContext = (0, import_react33.useContext)(I18nContext);
|
|
9241
9492
|
const locale = i18nContext?.locale ?? localeProp ?? "en";
|
|
9242
9493
|
const strings = resolveChatStrings(locale);
|
|
9243
9494
|
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: `resource-chip ${disabled ? "disabled" : ""}`, children: [
|
|
@@ -9256,7 +9507,7 @@ var ResourceChip = (0, import_react32.memo)(function ResourceChip2({
|
|
|
9256
9507
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("style", { children: resourceChipStyles })
|
|
9257
9508
|
] });
|
|
9258
9509
|
});
|
|
9259
|
-
var ResourceChipList = (0,
|
|
9510
|
+
var ResourceChipList = (0, import_react33.memo)(function ResourceChipList2({
|
|
9260
9511
|
resources,
|
|
9261
9512
|
onRemove,
|
|
9262
9513
|
disabled
|
|
@@ -9335,7 +9586,7 @@ var resourceChipStyles = `
|
|
|
9335
9586
|
`;
|
|
9336
9587
|
|
|
9337
9588
|
// src/renderer/hooks/useWindowBackgroundSync.ts
|
|
9338
|
-
var
|
|
9589
|
+
var import_react34 = require("react");
|
|
9339
9590
|
var cachedPlatform = null;
|
|
9340
9591
|
var getPlatform = () => {
|
|
9341
9592
|
if (cachedPlatform !== null) return cachedPlatform;
|
|
@@ -9353,7 +9604,7 @@ var setBackgroundColor = (color) => {
|
|
|
9353
9604
|
}
|
|
9354
9605
|
};
|
|
9355
9606
|
function useWindowBackgroundSync(isDarkMode) {
|
|
9356
|
-
(0,
|
|
9607
|
+
(0, import_react34.useEffect)(() => {
|
|
9357
9608
|
if (getPlatform() !== "win32") return;
|
|
9358
9609
|
const colors = getBaseColors(isDarkMode);
|
|
9359
9610
|
setBackgroundColor(colors.bg);
|
|
@@ -9362,7 +9613,7 @@ function useWindowBackgroundSync(isDarkMode) {
|
|
|
9362
9613
|
|
|
9363
9614
|
// src/renderer/components/FloatingChat.tsx
|
|
9364
9615
|
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
9365
|
-
var FloatingChat = (0,
|
|
9616
|
+
var FloatingChat = (0, import_react35.memo)(function FloatingChat2({
|
|
9366
9617
|
messages,
|
|
9367
9618
|
isLoading,
|
|
9368
9619
|
isStreaming,
|
|
@@ -9385,8 +9636,8 @@ var FloatingChat = (0, import_react34.memo)(function FloatingChat2({
|
|
|
9385
9636
|
header,
|
|
9386
9637
|
footer
|
|
9387
9638
|
}) {
|
|
9388
|
-
const chatContainerRef = (0,
|
|
9389
|
-
const chatInputRef = (0,
|
|
9639
|
+
const chatContainerRef = (0, import_react35.useRef)(null);
|
|
9640
|
+
const chatInputRef = (0, import_react35.useRef)(null);
|
|
9390
9641
|
useChatStyles();
|
|
9391
9642
|
useFocusPersistence({
|
|
9392
9643
|
containerRef: chatContainerRef,
|
|
@@ -9398,18 +9649,18 @@ var FloatingChat = (0, import_react34.memo)(function FloatingChat2({
|
|
|
9398
9649
|
const { themeClass, isDarkMode } = useResolvedTheme(themeMode);
|
|
9399
9650
|
const accentStyle = useAccentStyle(resolvedConfig?.accentColor);
|
|
9400
9651
|
useWindowBackgroundSync(isDarkMode);
|
|
9401
|
-
const rootStyle = (0,
|
|
9652
|
+
const rootStyle = (0, import_react35.useMemo)(() => ({
|
|
9402
9653
|
...accentStyle || {},
|
|
9403
9654
|
minHeight: "100vh",
|
|
9404
9655
|
minWidth: "100vw"
|
|
9405
9656
|
}), [accentStyle]);
|
|
9406
9657
|
const resolvedLogo = logo ?? resolvedConfig?.logo;
|
|
9407
9658
|
const resolvedLocale = resolvedConfig?.locale ?? locale;
|
|
9408
|
-
const resolvedStrings = (0,
|
|
9659
|
+
const resolvedStrings = (0, import_react35.useMemo)(
|
|
9409
9660
|
() => resolveChatStrings(resolvedLocale, resolvedConfig?.strings),
|
|
9410
9661
|
[resolvedLocale, resolvedConfig?.strings]
|
|
9411
9662
|
);
|
|
9412
|
-
const headerConfig = (0,
|
|
9663
|
+
const headerConfig = (0, import_react35.useMemo)(
|
|
9413
9664
|
() => {
|
|
9414
9665
|
if (!resolvedConfig) {
|
|
9415
9666
|
return resolvedLogo ? { logo: resolvedLogo } : void 0;
|
|
@@ -9422,7 +9673,7 @@ var FloatingChat = (0, import_react34.memo)(function FloatingChat2({
|
|
|
9422
9673
|
[resolvedConfig, resolvedLogo]
|
|
9423
9674
|
);
|
|
9424
9675
|
const { logoNode, showPin, showClose, isPinned, togglePin, resolvedOnClose } = useChatHeader(headerConfig);
|
|
9425
|
-
const emptyLogoNode = (0,
|
|
9676
|
+
const emptyLogoNode = (0, import_react35.useMemo)(() => resolveLogoNode(resolvedLogo, "empty"), [resolvedLogo]);
|
|
9426
9677
|
const inputPlaceholder = placeholder ?? resolvedStrings.inputPlaceholder;
|
|
9427
9678
|
const showHeader = !!(header || logoNode || showPin || showClose);
|
|
9428
9679
|
const defaultHeader = /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("header", { className: "flex h-9 flex-shrink-0 items-center px-2 border-b chat-divider-border", children: [
|
|
@@ -9467,7 +9718,7 @@ var FloatingChat = (0, import_react34.memo)(function FloatingChat2({
|
|
|
9467
9718
|
] })
|
|
9468
9719
|
] });
|
|
9469
9720
|
const resolvedHeader = header ?? (showHeader ? defaultHeader : null);
|
|
9470
|
-
const defaultRenderMessage = (0,
|
|
9721
|
+
const defaultRenderMessage = (0, import_react35.useCallback)(
|
|
9471
9722
|
(message) => {
|
|
9472
9723
|
if (message.role === "tool") return null;
|
|
9473
9724
|
const isUser = message.role === "user";
|
|
@@ -9481,7 +9732,7 @@ var FloatingChat = (0, import_react34.memo)(function FloatingChat2({
|
|
|
9481
9732
|
},
|
|
9482
9733
|
[renderContent]
|
|
9483
9734
|
);
|
|
9484
|
-
const defaultRenderHitl = (0,
|
|
9735
|
+
const defaultRenderHitl = (0, import_react35.useCallback)(
|
|
9485
9736
|
(interrupt, onApprove, onReject) => /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "p-4 bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 rounded-lg m-2", children: [
|
|
9486
9737
|
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "font-medium mb-2", children: interrupt.type === "approval_request" ? resolvedStrings.hitlApprovalRequired : resolvedStrings.hitlInputRequired }),
|
|
9487
9738
|
interrupt.tool && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("p", { className: "text-sm mb-2", children: [
|
|
@@ -9562,6 +9813,7 @@ var FloatingChat = (0, import_react34.memo)(function FloatingChat2({
|
|
|
9562
9813
|
stopLabel: resolvedStrings.inputStop,
|
|
9563
9814
|
isStreaming,
|
|
9564
9815
|
isLoading,
|
|
9816
|
+
allowEmptySubmit: !!sessionResources && sessionResources.length > 0,
|
|
9565
9817
|
disabled: !!pendingInterrupt || isLoading && !isStreaming,
|
|
9566
9818
|
autoFocus: true
|
|
9567
9819
|
}
|
|
@@ -9571,10 +9823,10 @@ var FloatingChat = (0, import_react34.memo)(function FloatingChat2({
|
|
|
9571
9823
|
});
|
|
9572
9824
|
|
|
9573
9825
|
// src/renderer/components/HistoryList.tsx
|
|
9574
|
-
var
|
|
9826
|
+
var import_react36 = require("react");
|
|
9575
9827
|
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
9576
9828
|
function DeleteButton({ onClick, title, colors }) {
|
|
9577
|
-
const [isHovered, setIsHovered] = (0,
|
|
9829
|
+
const [isHovered, setIsHovered] = (0, import_react36.useState)(false);
|
|
9578
9830
|
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
9579
9831
|
"button",
|
|
9580
9832
|
{
|
|
@@ -9618,7 +9870,7 @@ function DeleteButton({ onClick, title, colors }) {
|
|
|
9618
9870
|
);
|
|
9619
9871
|
}
|
|
9620
9872
|
function LoadMoreButton({ onClick, colors, children }) {
|
|
9621
|
-
const [isHovered, setIsHovered] = (0,
|
|
9873
|
+
const [isHovered, setIsHovered] = (0, import_react36.useState)(false);
|
|
9622
9874
|
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
9623
9875
|
"button",
|
|
9624
9876
|
{
|
|
@@ -9668,7 +9920,7 @@ function formatRelativeTime(dateStr, strings) {
|
|
|
9668
9920
|
return date.toLocaleDateString(void 0, { month: "short", day: "numeric" });
|
|
9669
9921
|
}
|
|
9670
9922
|
}
|
|
9671
|
-
var HistoryList = (0,
|
|
9923
|
+
var HistoryList = (0, import_react36.memo)(function HistoryList2({
|
|
9672
9924
|
conversations,
|
|
9673
9925
|
selectedId,
|
|
9674
9926
|
isLoading,
|
|
@@ -9680,13 +9932,13 @@ var HistoryList = (0, import_react35.memo)(function HistoryList2({
|
|
|
9680
9932
|
isDarkMode = false,
|
|
9681
9933
|
strings = {}
|
|
9682
9934
|
}) {
|
|
9683
|
-
const [hoveredId, setHoveredId] = (0,
|
|
9684
|
-
const loadMoreRef = (0,
|
|
9685
|
-
const isLoadingRef = (0,
|
|
9686
|
-
(0,
|
|
9935
|
+
const [hoveredId, setHoveredId] = (0, import_react36.useState)(null);
|
|
9936
|
+
const loadMoreRef = (0, import_react36.useRef)(null);
|
|
9937
|
+
const isLoadingRef = (0, import_react36.useRef)(isLoading);
|
|
9938
|
+
(0, import_react36.useEffect)(() => {
|
|
9687
9939
|
isLoadingRef.current = isLoading;
|
|
9688
9940
|
}, [isLoading]);
|
|
9689
|
-
(0,
|
|
9941
|
+
(0, import_react36.useEffect)(() => {
|
|
9690
9942
|
if (!hasMore || loadError || !onLoadMore) return;
|
|
9691
9943
|
const sentinel = loadMoreRef.current;
|
|
9692
9944
|
if (!sentinel) return;
|
|
@@ -9783,10 +10035,10 @@ var HistoryList = (0, import_react35.memo)(function HistoryList2({
|
|
|
9783
10035
|
});
|
|
9784
10036
|
|
|
9785
10037
|
// src/renderer/components/HistoryModal.tsx
|
|
9786
|
-
var
|
|
10038
|
+
var import_react37 = require("react");
|
|
9787
10039
|
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
9788
10040
|
var ANIMATION_DURATION = 120;
|
|
9789
|
-
var HistoryModal = (0,
|
|
10041
|
+
var HistoryModal = (0, import_react37.memo)(function HistoryModal2({
|
|
9790
10042
|
isOpen,
|
|
9791
10043
|
onClose,
|
|
9792
10044
|
title,
|
|
@@ -9794,10 +10046,10 @@ var HistoryModal = (0, import_react36.memo)(function HistoryModal2({
|
|
|
9794
10046
|
children,
|
|
9795
10047
|
isDarkMode = false
|
|
9796
10048
|
}) {
|
|
9797
|
-
const modalRef = (0,
|
|
9798
|
-
const [isClosing, setIsClosing] = (0,
|
|
9799
|
-
const [shouldRender, setShouldRender] = (0,
|
|
9800
|
-
(0,
|
|
10049
|
+
const modalRef = (0, import_react37.useRef)(null);
|
|
10050
|
+
const [isClosing, setIsClosing] = (0, import_react37.useState)(false);
|
|
10051
|
+
const [shouldRender, setShouldRender] = (0, import_react37.useState)(isOpen);
|
|
10052
|
+
(0, import_react37.useEffect)(() => {
|
|
9801
10053
|
if (isOpen) {
|
|
9802
10054
|
setShouldRender(true);
|
|
9803
10055
|
setIsClosing(false);
|
|
@@ -9809,7 +10061,7 @@ var HistoryModal = (0, import_react36.memo)(function HistoryModal2({
|
|
|
9809
10061
|
}, ANIMATION_DURATION);
|
|
9810
10062
|
}
|
|
9811
10063
|
}, [isOpen, shouldRender, isClosing]);
|
|
9812
|
-
const handleClose = (0,
|
|
10064
|
+
const handleClose = (0, import_react37.useCallback)(() => {
|
|
9813
10065
|
setIsClosing(true);
|
|
9814
10066
|
setTimeout(() => {
|
|
9815
10067
|
setShouldRender(false);
|
|
@@ -9817,7 +10069,7 @@ var HistoryModal = (0, import_react36.memo)(function HistoryModal2({
|
|
|
9817
10069
|
onClose();
|
|
9818
10070
|
}, ANIMATION_DURATION);
|
|
9819
10071
|
}, [onClose]);
|
|
9820
|
-
(0,
|
|
10072
|
+
(0, import_react37.useEffect)(() => {
|
|
9821
10073
|
if (!shouldRender || isClosing) return;
|
|
9822
10074
|
const handleKeyDown = (e) => {
|
|
9823
10075
|
if (e.key === "Escape") {
|
|
@@ -9828,11 +10080,11 @@ var HistoryModal = (0, import_react36.memo)(function HistoryModal2({
|
|
|
9828
10080
|
document.addEventListener("keydown", handleKeyDown);
|
|
9829
10081
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
9830
10082
|
}, [shouldRender, isClosing, handleClose]);
|
|
9831
|
-
(0,
|
|
10083
|
+
(0, import_react37.useEffect)(() => {
|
|
9832
10084
|
if (!isOpen || !modalRef.current) return;
|
|
9833
10085
|
modalRef.current.focus();
|
|
9834
10086
|
}, [isOpen]);
|
|
9835
|
-
const handleBackdropClick = (0,
|
|
10087
|
+
const handleBackdropClick = (0, import_react37.useCallback)(
|
|
9836
10088
|
(e) => {
|
|
9837
10089
|
if (e.target === e.currentTarget && !isClosing) {
|
|
9838
10090
|
handleClose();
|
|
@@ -9971,7 +10223,7 @@ var HistoryModal = (0, import_react36.memo)(function HistoryModal2({
|
|
|
9971
10223
|
});
|
|
9972
10224
|
|
|
9973
10225
|
// src/renderer/components/CompactChat.tsx
|
|
9974
|
-
var
|
|
10226
|
+
var import_react38 = require("react");
|
|
9975
10227
|
var import_react_dom = require("react-dom");
|
|
9976
10228
|
|
|
9977
10229
|
// src/renderer/components/PanelControls.tsx
|
|
@@ -10011,7 +10263,7 @@ var PanelControls = {
|
|
|
10011
10263
|
|
|
10012
10264
|
// src/renderer/components/CompactChat.tsx
|
|
10013
10265
|
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
10014
|
-
var CompactChat = (0,
|
|
10266
|
+
var CompactChat = (0, import_react38.memo)(function CompactChat2({
|
|
10015
10267
|
adapter,
|
|
10016
10268
|
config,
|
|
10017
10269
|
logo,
|
|
@@ -10047,12 +10299,12 @@ var CompactChat = (0, import_react37.memo)(function CompactChat2({
|
|
|
10047
10299
|
const { themeClass, isDarkMode: resolvedIsDarkMode } = useResolvedTheme(themeMode);
|
|
10048
10300
|
const accentStyle = useAccentStyle(resolvedConfig?.accentColor);
|
|
10049
10301
|
const resolvedLogo = logo ?? resolvedConfig?.logo;
|
|
10050
|
-
const baseStrings = (0,
|
|
10302
|
+
const baseStrings = (0, import_react38.useMemo)(
|
|
10051
10303
|
() => resolveChatStrings(resolvedConfig?.locale, resolvedConfig?.strings),
|
|
10052
10304
|
[resolvedConfig?.locale, resolvedConfig?.strings]
|
|
10053
10305
|
);
|
|
10054
|
-
const mergedStrings = (0,
|
|
10055
|
-
const headerConfig = (0,
|
|
10306
|
+
const mergedStrings = (0, import_react38.useMemo)(() => ({ ...baseStrings, ...strings }), [baseStrings, strings]);
|
|
10307
|
+
const headerConfig = (0, import_react38.useMemo)(
|
|
10056
10308
|
() => {
|
|
10057
10309
|
if (!resolvedConfig) {
|
|
10058
10310
|
return resolvedLogo ? { logo: resolvedLogo } : void 0;
|
|
@@ -10065,13 +10317,14 @@ var CompactChat = (0, import_react37.memo)(function CompactChat2({
|
|
|
10065
10317
|
[resolvedConfig, resolvedLogo]
|
|
10066
10318
|
);
|
|
10067
10319
|
const { logoNode, showPin, showClose, isPinned, togglePin, resolvedOnClose } = useChatHeader(headerConfig);
|
|
10068
|
-
const emptyLogoNode = (0,
|
|
10320
|
+
const emptyLogoNode = (0, import_react38.useMemo)(() => resolveLogoNode(resolvedLogo, "empty"), [resolvedLogo]);
|
|
10069
10321
|
const { isEmbedded, toggleMode, hide: hidePanel } = useChatPanel();
|
|
10070
|
-
const chatContainerRef = (0,
|
|
10071
|
-
const chatInputRef = (0,
|
|
10072
|
-
const [showHistory, setShowHistory] = (0,
|
|
10073
|
-
|
|
10074
|
-
const
|
|
10322
|
+
const chatContainerRef = (0, import_react38.useRef)(null);
|
|
10323
|
+
const chatInputRef = (0, import_react38.useRef)(null);
|
|
10324
|
+
const [showHistory, setShowHistory] = (0, import_react38.useState)(false);
|
|
10325
|
+
useWindowDragLock(showHistory);
|
|
10326
|
+
const [connectionAlert, setConnectionAlert] = (0, import_react38.useState)(null);
|
|
10327
|
+
const portalContainerRef = (0, import_react38.useRef)(inputPortalContainer ?? null);
|
|
10075
10328
|
portalContainerRef.current = inputPortalContainer ?? null;
|
|
10076
10329
|
const shouldRenderInputExternally = !!inputPortalContainer;
|
|
10077
10330
|
const inputPlaceholder = placeholder ?? mergedStrings.inputPlaceholder;
|
|
@@ -10110,49 +10363,55 @@ var CompactChat = (0, import_react37.memo)(function CompactChat2({
|
|
|
10110
10363
|
onError
|
|
10111
10364
|
});
|
|
10112
10365
|
const resourcePicker = useResourcePicker({ adapter });
|
|
10113
|
-
const resourceProviders = (0,
|
|
10366
|
+
const resourceProviders = (0, import_react38.useMemo)(
|
|
10114
10367
|
() => resourcePicker.providers.filter((p) => p.hasGetList),
|
|
10115
10368
|
[resourcePicker.providers]
|
|
10116
10369
|
);
|
|
10117
|
-
const handleHitlCancel = (0,
|
|
10370
|
+
const handleHitlCancel = (0, import_react38.useCallback)(() => {
|
|
10118
10371
|
if (chat.pendingInterrupt?.type === "approval_request") {
|
|
10119
10372
|
chat.rejectHitl();
|
|
10120
10373
|
} else {
|
|
10121
10374
|
chat.submitHitlInput({ cancelled: true });
|
|
10122
10375
|
}
|
|
10123
10376
|
}, [chat.pendingInterrupt?.type, chat.rejectHitl, chat.submitHitlInput]);
|
|
10124
|
-
const handleSendWithResources = (0,
|
|
10125
|
-
const resources = resourcePicker.attachedResources;
|
|
10126
|
-
|
|
10127
|
-
|
|
10128
|
-
|
|
10129
|
-
|
|
10377
|
+
const handleSendWithResources = (0, import_react38.useCallback)(async (content) => {
|
|
10378
|
+
const resources = [...resourcePicker.attachedResources];
|
|
10379
|
+
const sent = await chat.trySendMessage(
|
|
10380
|
+
content,
|
|
10381
|
+
resources.length > 0 ? { attachedResources: resources } : void 0
|
|
10382
|
+
);
|
|
10383
|
+
if (sent) {
|
|
10384
|
+
resourcePicker.clearAttachedResources();
|
|
10385
|
+
}
|
|
10386
|
+
return sent;
|
|
10387
|
+
}, [chat.trySendMessage, resourcePicker.attachedResources, resourcePicker.clearAttachedResources]);
|
|
10388
|
+
(0, import_react38.useEffect)(() => {
|
|
10130
10389
|
if (sendMessageRef) {
|
|
10131
10390
|
sendMessageRef.current = chat.sendMessage;
|
|
10132
10391
|
}
|
|
10133
10392
|
}, [sendMessageRef, chat.sendMessage]);
|
|
10134
|
-
(0,
|
|
10393
|
+
(0, import_react38.useEffect)(() => {
|
|
10135
10394
|
if (newConversationRef) {
|
|
10136
10395
|
newConversationRef.current = chat.newConversation;
|
|
10137
10396
|
}
|
|
10138
10397
|
}, [newConversationRef, chat.newConversation]);
|
|
10139
|
-
(0,
|
|
10398
|
+
(0, import_react38.useEffect)(() => {
|
|
10140
10399
|
if (parentFocusInputRef) {
|
|
10141
10400
|
parentFocusInputRef.current = () => chatInputRef.current?.focus();
|
|
10142
10401
|
}
|
|
10143
10402
|
}, [parentFocusInputRef]);
|
|
10144
|
-
(0,
|
|
10403
|
+
(0, import_react38.useEffect)(() => {
|
|
10145
10404
|
if (parentSetTextRef) {
|
|
10146
10405
|
parentSetTextRef.current = (text) => chatInputRef.current?.setValue(text);
|
|
10147
10406
|
}
|
|
10148
10407
|
}, [parentSetTextRef]);
|
|
10149
|
-
(0,
|
|
10408
|
+
(0, import_react38.useEffect)(() => {
|
|
10150
10409
|
if (!adapter.onFocusInput) return;
|
|
10151
10410
|
return adapter.onFocusInput(() => {
|
|
10152
10411
|
chatInputRef.current?.focus();
|
|
10153
10412
|
});
|
|
10154
10413
|
}, [adapter]);
|
|
10155
|
-
(0,
|
|
10414
|
+
(0, import_react38.useEffect)(() => {
|
|
10156
10415
|
if (onMessageReceived && chat.messages.length > 0) {
|
|
10157
10416
|
const lastMessage = chat.messages[chat.messages.length - 1];
|
|
10158
10417
|
if (lastMessage.role === "assistant" && !lastMessage.isStreaming) {
|
|
@@ -10160,12 +10419,12 @@ var CompactChat = (0, import_react37.memo)(function CompactChat2({
|
|
|
10160
10419
|
}
|
|
10161
10420
|
}
|
|
10162
10421
|
}, [chat.messages, onMessageReceived]);
|
|
10163
|
-
(0,
|
|
10422
|
+
(0, import_react38.useEffect)(() => {
|
|
10164
10423
|
if (onLoadingChange) {
|
|
10165
10424
|
onLoadingChange(chat.isLoading);
|
|
10166
10425
|
}
|
|
10167
10426
|
}, [chat.isLoading, onLoadingChange]);
|
|
10168
|
-
(0,
|
|
10427
|
+
(0, import_react38.useEffect)(() => {
|
|
10169
10428
|
if (onStateChange) {
|
|
10170
10429
|
onStateChange({
|
|
10171
10430
|
messages: chat.messages,
|
|
@@ -10173,24 +10432,24 @@ var CompactChat = (0, import_react37.memo)(function CompactChat2({
|
|
|
10173
10432
|
});
|
|
10174
10433
|
}
|
|
10175
10434
|
}, [chat.messages, chat.conversationId, onStateChange]);
|
|
10176
|
-
(0,
|
|
10435
|
+
(0, import_react38.useEffect)(() => {
|
|
10177
10436
|
if (connection.isConnected) {
|
|
10178
10437
|
resourcePicker.refreshProviders();
|
|
10179
10438
|
}
|
|
10180
10439
|
}, [connection.isConnected]);
|
|
10181
|
-
(0,
|
|
10440
|
+
(0, import_react38.useEffect)(() => {
|
|
10182
10441
|
if (showHistory && connection.isConnected) {
|
|
10183
10442
|
conversations.loadConversations();
|
|
10184
10443
|
}
|
|
10185
10444
|
}, [showHistory, connection.isConnected]);
|
|
10186
|
-
const handleSelectConversation = (0,
|
|
10445
|
+
const handleSelectConversation = (0, import_react38.useCallback)(
|
|
10187
10446
|
async (id) => {
|
|
10188
10447
|
setShowHistory(false);
|
|
10189
10448
|
await chat.loadConversation(id);
|
|
10190
10449
|
},
|
|
10191
10450
|
[chat]
|
|
10192
10451
|
);
|
|
10193
|
-
const handleDeleteConversation = (0,
|
|
10452
|
+
const handleDeleteConversation = (0, import_react38.useCallback)(
|
|
10194
10453
|
async (id) => {
|
|
10195
10454
|
await conversations.deleteConversation(id);
|
|
10196
10455
|
if (id === chat.conversationId) {
|
|
@@ -10199,14 +10458,14 @@ var CompactChat = (0, import_react37.memo)(function CompactChat2({
|
|
|
10199
10458
|
},
|
|
10200
10459
|
[conversations, chat]
|
|
10201
10460
|
);
|
|
10202
|
-
const handleNewChat = (0,
|
|
10461
|
+
const handleNewChat = (0, import_react38.useCallback)(() => {
|
|
10203
10462
|
chat.newConversation();
|
|
10204
10463
|
setShowHistory(false);
|
|
10205
10464
|
setTimeout(() => {
|
|
10206
10465
|
chatInputRef.current?.focus();
|
|
10207
10466
|
}, 0);
|
|
10208
10467
|
}, [chat]);
|
|
10209
|
-
(0,
|
|
10468
|
+
(0, import_react38.useEffect)(() => {
|
|
10210
10469
|
const handleKeyDown = (e) => {
|
|
10211
10470
|
const isMac2 = navigator.platform.includes("Mac");
|
|
10212
10471
|
const modifierKey = isMac2 ? e.metaKey : e.ctrlKey;
|
|
@@ -10220,20 +10479,19 @@ var CompactChat = (0, import_react37.memo)(function CompactChat2({
|
|
|
10220
10479
|
}, [handleNewChat]);
|
|
10221
10480
|
const isMac = typeof navigator !== "undefined" && navigator.platform.includes("Mac");
|
|
10222
10481
|
const shortcutKey = isMac ? "\u2318N" : "Ctrl+N";
|
|
10223
|
-
const defaultRenderMessage = (0,
|
|
10482
|
+
const defaultRenderMessage = (0, import_react38.useCallback)((message) => {
|
|
10224
10483
|
if (message.role === "tool") return null;
|
|
10225
10484
|
const isUser = message.role === "user";
|
|
10226
|
-
const
|
|
10227
|
-
|
|
10228
|
-
|
|
10229
|
-
|
|
10230
|
-
|
|
10231
|
-
|
|
10232
|
-
|
|
10233
|
-
const
|
|
10234
|
-
const isToolCallsStreaming = message.isToolCallsStreaming ?? ((message.toolCalls?.some((tc) => tc.status === "running") ?? false) || (message.blocks?.some((b) => b.type === "tool_call" && b.toolStatus === "running") ?? false));
|
|
10485
|
+
const {
|
|
10486
|
+
displayBlocks,
|
|
10487
|
+
isEffectivelyComplete,
|
|
10488
|
+
showIntermediateSteps,
|
|
10489
|
+
showStreamingTimeline,
|
|
10490
|
+
showThinkingSection
|
|
10491
|
+
} = getAssistantDisplayState(message);
|
|
10492
|
+
const isToolCallsStreaming = message.isToolCallsStreaming ?? ((message.toolCalls?.some((tc) => tc.status === "running") ?? false) || (displayBlocks?.some((b) => b.type === "tool_call" && b.toolStatus === "running") ?? false));
|
|
10235
10493
|
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: `flex ${isUser ? "justify-end" : "justify-start"} mb-4`, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: `text-left ${isUser ? "max-w-[80%]" : "w-full"}`, children: [
|
|
10236
|
-
!isUser && showIntermediateSteps &&
|
|
10494
|
+
!isUser && showIntermediateSteps && displayBlocks && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(IntermediateSteps, { blocks: displayBlocks, strings: mergedStrings }),
|
|
10237
10495
|
showThinkingSection && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
10238
10496
|
ThinkingSection,
|
|
10239
10497
|
{
|
|
@@ -10241,18 +10499,18 @@ var CompactChat = (0, import_react37.memo)(function CompactChat2({
|
|
|
10241
10499
|
currentThinking: message.currentThinking,
|
|
10242
10500
|
isStreaming: message.isThinkingStreaming,
|
|
10243
10501
|
isPaused: message.isThinkingPaused,
|
|
10244
|
-
isComplete:
|
|
10502
|
+
isComplete: isEffectivelyComplete,
|
|
10245
10503
|
strings: mergedStrings
|
|
10246
10504
|
}
|
|
10247
10505
|
),
|
|
10248
|
-
showStreamingTimeline &&
|
|
10506
|
+
showStreamingTimeline && displayBlocks && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
10249
10507
|
StreamingTimeline,
|
|
10250
10508
|
{
|
|
10251
|
-
blocks:
|
|
10509
|
+
blocks: displayBlocks,
|
|
10252
10510
|
currentThinking: message.currentThinking,
|
|
10253
10511
|
isThinkingStreaming: message.isThinkingStreaming,
|
|
10254
10512
|
isToolCallsStreaming,
|
|
10255
|
-
isComplete:
|
|
10513
|
+
isComplete: isEffectivelyComplete,
|
|
10256
10514
|
strings: mergedStrings
|
|
10257
10515
|
}
|
|
10258
10516
|
),
|
|
@@ -10274,11 +10532,11 @@ var CompactChat = (0, import_react37.memo)(function CompactChat2({
|
|
|
10274
10532
|
] }) });
|
|
10275
10533
|
}, [mergedStrings, linkHandler]);
|
|
10276
10534
|
const containerClass = floating ? `relative chat-window-container ${themeClass}${className ? ` ${className}` : ""}` : `relative flex h-full flex-col bg-[var(--chat-bg)] text-[var(--chat-text)] ${themeClass}${className ? ` ${className}` : ""}`;
|
|
10277
|
-
const baseColors = (0,
|
|
10535
|
+
const baseColors = (0, import_react38.useMemo)(() => {
|
|
10278
10536
|
if (!floating) return null;
|
|
10279
10537
|
return getBaseColors(resolvedIsDarkMode);
|
|
10280
10538
|
}, [floating, resolvedIsDarkMode]);
|
|
10281
|
-
const containerStyle = (0,
|
|
10539
|
+
const containerStyle = (0, import_react38.useMemo)(() => {
|
|
10282
10540
|
const baseStyle = floating && baseColors ? {
|
|
10283
10541
|
...accentStyle,
|
|
10284
10542
|
// Override CSS variables with tinted colors for consistency with app
|
|
@@ -10306,7 +10564,7 @@ var CompactChat = (0, import_react37.memo)(function CompactChat2({
|
|
|
10306
10564
|
"data-chat-font-size": resolvedConfig?.fontSize || "normal",
|
|
10307
10565
|
children: [
|
|
10308
10566
|
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(PanelResizer, {}),
|
|
10309
|
-
!hideHeader && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("header", { className: "flex flex-shrink-0 items-center px-2 border-b chat-divider-border", style: { height: 42, WebkitAppRegion: "drag" }, children: isEmbedded ? (
|
|
10567
|
+
!hideHeader && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("header", { className: "flex flex-shrink-0 items-center px-2 border-b chat-divider-border chat-drag-region", style: { height: 42, WebkitAppRegion: "drag" }, children: isEmbedded ? (
|
|
10310
10568
|
// Embedded mode: left-aligned buttons (collapse, float, history, new chat)
|
|
10311
10569
|
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center gap-0.5", style: { WebkitAppRegion: "no-drag" }, children: [
|
|
10312
10570
|
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "chat-tooltip-wrapper", children: [
|
|
@@ -10481,6 +10739,7 @@ var CompactChat = (0, import_react37.memo)(function CompactChat2({
|
|
|
10481
10739
|
(() => {
|
|
10482
10740
|
if (hideInput && !shouldRenderInputExternally) return null;
|
|
10483
10741
|
const disableInput = !!chat.pendingInterrupt || chat.isLoading && !chat.isStreaming;
|
|
10742
|
+
const allowEmptySubmit = resourcePicker.attachedResources.length > 0 || chat.sessionResources.length > 0;
|
|
10484
10743
|
const addResourceButtonSlot = resourceProviders.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
10485
10744
|
AddResourceButton,
|
|
10486
10745
|
{
|
|
@@ -10514,6 +10773,7 @@ var CompactChat = (0, import_react37.memo)(function CompactChat2({
|
|
|
10514
10773
|
disabled: disableInput,
|
|
10515
10774
|
isStreaming: chat.isStreaming,
|
|
10516
10775
|
isLoading: chat.isLoading,
|
|
10776
|
+
allowEmptySubmit,
|
|
10517
10777
|
autoFocus: true,
|
|
10518
10778
|
leftSlot: addResourceButtonSlot
|
|
10519
10779
|
}
|
|
@@ -10662,5 +10922,6 @@ var CompactChat = (0, import_react37.memo)(function CompactChat2({
|
|
|
10662
10922
|
useResourcePicker,
|
|
10663
10923
|
useStandaloneI18n,
|
|
10664
10924
|
useStandaloneTheme,
|
|
10665
|
-
useTheme
|
|
10925
|
+
useTheme,
|
|
10926
|
+
useWindowDragLock
|
|
10666
10927
|
});
|