@yushaw/sanqian-chat 0.2.20 → 0.2.22
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 +633 -357
- package/dist/renderer/index.mjs +591 -316
- 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,14 @@ 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 inputRevisionRef = (0, import_react23.useRef)(0);
|
|
7873
|
+
const canSend = (text.trim().length > 0 || allowEmptySubmit) && !disabled && !isLoading;
|
|
7646
7874
|
const showStopButton = isStreaming && !!onStop;
|
|
7647
7875
|
const showSpinner = isLoading && !showStopButton;
|
|
7648
|
-
(0,
|
|
7876
|
+
(0, import_react23.useImperativeHandle)(
|
|
7649
7877
|
ref,
|
|
7650
7878
|
() => ({
|
|
7651
7879
|
focus: () => textareaRef.current?.focus(),
|
|
@@ -7655,26 +7883,46 @@ var ChatInput = (0, import_react22.memo)(
|
|
|
7655
7883
|
}),
|
|
7656
7884
|
[text]
|
|
7657
7885
|
);
|
|
7658
|
-
(0,
|
|
7886
|
+
(0, import_react23.useEffect)(() => {
|
|
7659
7887
|
if (autoFocus) {
|
|
7660
7888
|
const timer = setTimeout(() => textareaRef.current?.focus(), 100);
|
|
7661
7889
|
return () => clearTimeout(timer);
|
|
7662
7890
|
}
|
|
7663
7891
|
}, [autoFocus]);
|
|
7664
|
-
const handleSubmit = (0,
|
|
7665
|
-
(e) => {
|
|
7892
|
+
const handleSubmit = (0, import_react23.useCallback)(
|
|
7893
|
+
async (e) => {
|
|
7666
7894
|
e?.preventDefault();
|
|
7667
7895
|
if (!canSend) return;
|
|
7668
|
-
|
|
7896
|
+
if (submitInFlightRef.current) return;
|
|
7897
|
+
const draft = text;
|
|
7898
|
+
const payload = draft.trim();
|
|
7899
|
+
const submitRevision = inputRevisionRef.current;
|
|
7900
|
+
submitInFlightRef.current = true;
|
|
7669
7901
|
setText("");
|
|
7902
|
+
const restoreDraft = () => {
|
|
7903
|
+
setText((current) => {
|
|
7904
|
+
if (inputRevisionRef.current !== submitRevision) return current;
|
|
7905
|
+
return current.length === 0 ? draft : current;
|
|
7906
|
+
});
|
|
7907
|
+
};
|
|
7908
|
+
try {
|
|
7909
|
+
const result = await onSend(payload);
|
|
7910
|
+
if (result === false) {
|
|
7911
|
+
restoreDraft();
|
|
7912
|
+
}
|
|
7913
|
+
} catch {
|
|
7914
|
+
restoreDraft();
|
|
7915
|
+
} finally {
|
|
7916
|
+
submitInFlightRef.current = false;
|
|
7917
|
+
}
|
|
7670
7918
|
},
|
|
7671
7919
|
[text, canSend, onSend]
|
|
7672
7920
|
);
|
|
7673
|
-
const handleKeyDown = (0,
|
|
7921
|
+
const handleKeyDown = (0, import_react23.useCallback)(
|
|
7674
7922
|
(e) => {
|
|
7675
7923
|
if (e.key === "Enter" && !e.shiftKey && !e.nativeEvent.isComposing) {
|
|
7676
7924
|
e.preventDefault();
|
|
7677
|
-
handleSubmit();
|
|
7925
|
+
void handleSubmit();
|
|
7678
7926
|
}
|
|
7679
7927
|
if (e.key === "Escape" && showStopButton) {
|
|
7680
7928
|
e.preventDefault();
|
|
@@ -7685,60 +7933,73 @@ var ChatInput = (0, import_react22.memo)(
|
|
|
7685
7933
|
);
|
|
7686
7934
|
const leftPadding = leftSlot ? "2rem" : "0.75rem";
|
|
7687
7935
|
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
|
-
|
|
7936
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
7937
|
+
"form",
|
|
7938
|
+
{
|
|
7939
|
+
onSubmit: (e) => {
|
|
7940
|
+
void handleSubmit(e);
|
|
7941
|
+
},
|
|
7942
|
+
className: `chat-input-form${className ? ` ${className}` : ""}`,
|
|
7943
|
+
style,
|
|
7944
|
+
children: [
|
|
7945
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "chat-input-box", children: [
|
|
7946
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
7947
|
+
"div",
|
|
7948
|
+
{
|
|
7949
|
+
className: "chat-input-replica",
|
|
7950
|
+
style: { paddingLeft: leftPadding, paddingRight: rightPadding },
|
|
7951
|
+
"aria-hidden": "true",
|
|
7952
|
+
children: text + " "
|
|
7953
|
+
}
|
|
7954
|
+
),
|
|
7955
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
7956
|
+
"textarea",
|
|
7957
|
+
{
|
|
7958
|
+
ref: textareaRef,
|
|
7959
|
+
value: text,
|
|
7960
|
+
onChange: (e) => {
|
|
7961
|
+
inputRevisionRef.current += 1;
|
|
7962
|
+
setText(e.target.value);
|
|
7963
|
+
},
|
|
7964
|
+
onKeyDown: handleKeyDown,
|
|
7965
|
+
placeholder,
|
|
7966
|
+
disabled,
|
|
7967
|
+
rows: 1,
|
|
7968
|
+
className: "chat-input-textarea",
|
|
7969
|
+
style: { paddingLeft: leftPadding, paddingRight: rightPadding }
|
|
7970
|
+
}
|
|
7971
|
+
),
|
|
7972
|
+
leftSlot && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "chat-input-left-slot", children: leftSlot }),
|
|
7973
|
+
rightSlot && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "chat-input-right-slot", children: rightSlot })
|
|
7974
|
+
] }),
|
|
7975
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "chat-input-send-wrapper", children: [
|
|
7976
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
7977
|
+
"button",
|
|
7978
|
+
{
|
|
7979
|
+
type: showStopButton ? "button" : "submit",
|
|
7980
|
+
onClick: showStopButton ? onStop : void 0,
|
|
7981
|
+
disabled: !showStopButton && !canSend,
|
|
7982
|
+
className: "chat-input-send-btn",
|
|
7983
|
+
"aria-label": showStopButton ? stopLabel : sendLabel,
|
|
7984
|
+
children: showSpinner ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("svg", { viewBox: "0 0 24 24", fill: "none", className: "animate-spin", children: [
|
|
7985
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("circle", { cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4", opacity: "0.25" }),
|
|
7986
|
+
/* @__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" })
|
|
7987
|
+
] }) : 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" }) })
|
|
7988
|
+
}
|
|
7989
|
+
),
|
|
7990
|
+
showStopButton && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "chat-input-stop-tooltip", role: "note", children: [
|
|
7991
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { children: stopLabel }),
|
|
7992
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "chat-input-stop-hotkey", children: "Esc" })
|
|
7993
|
+
] })
|
|
7994
|
+
] })
|
|
7995
|
+
]
|
|
7996
|
+
}
|
|
7997
|
+
);
|
|
7737
7998
|
})
|
|
7738
7999
|
);
|
|
7739
8000
|
|
|
7740
8001
|
// src/renderer/components/HitlCard.tsx
|
|
7741
|
-
var
|
|
8002
|
+
var import_react24 = require("react");
|
|
7742
8003
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
7743
8004
|
var defaultStrings = {
|
|
7744
8005
|
approve: "Approve",
|
|
@@ -7777,7 +8038,7 @@ var riskColors = {
|
|
|
7777
8038
|
icon: "!!"
|
|
7778
8039
|
}
|
|
7779
8040
|
};
|
|
7780
|
-
var HitlCard = (0,
|
|
8041
|
+
var HitlCard = (0, import_react24.memo)(function HitlCard2({
|
|
7781
8042
|
interrupt,
|
|
7782
8043
|
onApprove,
|
|
7783
8044
|
onReject,
|
|
@@ -7789,16 +8050,16 @@ var HitlCard = (0, import_react23.memo)(function HitlCard2({
|
|
|
7789
8050
|
const t = { ...defaultStrings, ...strings };
|
|
7790
8051
|
const isApproval = interrupt.type === "approval_request";
|
|
7791
8052
|
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,
|
|
8053
|
+
const [answer, setAnswer] = (0, import_react24.useState)(interrupt.default || "");
|
|
8054
|
+
const [selectedIndices, setSelectedIndices] = (0, import_react24.useState)([]);
|
|
8055
|
+
const [isComposing, setIsComposing] = (0, import_react24.useState)(false);
|
|
8056
|
+
const [timeLeft, setTimeLeft] = (0, import_react24.useState)(interrupt.timeout ?? null);
|
|
8057
|
+
const [rememberChoice, setRememberChoice] = (0, import_react24.useState)(false);
|
|
8058
|
+
const inputRef = (0, import_react24.useRef)(null);
|
|
8059
|
+
const textareaRef = (0, import_react24.useRef)(null);
|
|
7799
8060
|
const riskLevel = interrupt.risk_level || "medium";
|
|
7800
8061
|
const riskStyle = riskColors[riskLevel];
|
|
7801
|
-
(0,
|
|
8062
|
+
(0, import_react24.useEffect)(() => {
|
|
7802
8063
|
if (isUserInput) {
|
|
7803
8064
|
if (!interrupt.options || interrupt.options.length === 0) {
|
|
7804
8065
|
inputRef.current?.focus();
|
|
@@ -7806,7 +8067,7 @@ var HitlCard = (0, import_react23.memo)(function HitlCard2({
|
|
|
7806
8067
|
}
|
|
7807
8068
|
}
|
|
7808
8069
|
}, [isUserInput, interrupt.options]);
|
|
7809
|
-
(0,
|
|
8070
|
+
(0, import_react24.useEffect)(() => {
|
|
7810
8071
|
if (timeLeft === null || timeLeft <= 0) return;
|
|
7811
8072
|
const timer = setInterval(() => {
|
|
7812
8073
|
setTimeLeft((prev) => {
|
|
@@ -8004,12 +8265,12 @@ var HitlCard = (0, import_react23.memo)(function HitlCard2({
|
|
|
8004
8265
|
});
|
|
8005
8266
|
|
|
8006
8267
|
// src/renderer/primitives/AlertBanner.tsx
|
|
8007
|
-
var
|
|
8268
|
+
var import_react25 = require("react");
|
|
8008
8269
|
var import_jsx_runtime13 = (
|
|
8009
8270
|
// Error icon (circle with X)
|
|
8010
8271
|
require("react/jsx-runtime")
|
|
8011
8272
|
);
|
|
8012
|
-
var AlertBanner = (0,
|
|
8273
|
+
var AlertBanner = (0, import_react25.memo)(function AlertBanner2({
|
|
8013
8274
|
type,
|
|
8014
8275
|
message,
|
|
8015
8276
|
action,
|
|
@@ -8019,7 +8280,7 @@ var AlertBanner = (0, import_react24.memo)(function AlertBanner2({
|
|
|
8019
8280
|
maxLines = 3,
|
|
8020
8281
|
strings
|
|
8021
8282
|
}) {
|
|
8022
|
-
const [isExpanded, setIsExpanded] = (0,
|
|
8283
|
+
const [isExpanded, setIsExpanded] = (0, import_react25.useState)(false);
|
|
8023
8284
|
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
8285
|
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("circle", { cx: "12", cy: "12", r: "10" }),
|
|
8025
8286
|
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { d: "M15 9l-6 6M9 9l6 6", strokeLinecap: "round" })
|
|
@@ -8081,10 +8342,10 @@ var AlertBanner = (0, import_react24.memo)(function AlertBanner2({
|
|
|
8081
8342
|
});
|
|
8082
8343
|
|
|
8083
8344
|
// src/renderer/components/AddResourceButton.tsx
|
|
8084
|
-
var
|
|
8345
|
+
var import_react27 = require("react");
|
|
8085
8346
|
|
|
8086
8347
|
// src/renderer/components/ResourcePicker.tsx
|
|
8087
|
-
var
|
|
8348
|
+
var import_react26 = require("react");
|
|
8088
8349
|
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
8089
8350
|
var STRINGS = {
|
|
8090
8351
|
en: {
|
|
@@ -8102,7 +8363,7 @@ var STRINGS = {
|
|
|
8102
8363
|
attached: "\u5DF2\u6DFB\u52A0"
|
|
8103
8364
|
}
|
|
8104
8365
|
};
|
|
8105
|
-
var ResourcePicker = (0,
|
|
8366
|
+
var ResourcePicker = (0, import_react26.memo)(function ResourcePicker2({
|
|
8106
8367
|
isOpen,
|
|
8107
8368
|
onClose,
|
|
8108
8369
|
providers,
|
|
@@ -8124,14 +8385,14 @@ var ResourcePicker = (0, import_react25.memo)(function ResourcePicker2({
|
|
|
8124
8385
|
className = ""
|
|
8125
8386
|
}) {
|
|
8126
8387
|
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,
|
|
8388
|
+
const pickerRef = (0, import_react26.useRef)(null);
|
|
8389
|
+
const searchInputRef = (0, import_react26.useRef)(null);
|
|
8390
|
+
const sentinelRef = (0, import_react26.useRef)(null);
|
|
8391
|
+
const listRef = (0, import_react26.useRef)(null);
|
|
8392
|
+
const scrollRestoredRef = (0, import_react26.useRef)(null);
|
|
8393
|
+
const [position, setPosition] = (0, import_react26.useState)({ top: 0, left: 0, width: 280 });
|
|
8133
8394
|
const getScrollKey = (providerId) => `resource-picker-scroll-${providerId}`;
|
|
8134
|
-
(0,
|
|
8395
|
+
(0, import_react26.useEffect)(() => {
|
|
8135
8396
|
if (!isOpen || !anchorRef?.current) return;
|
|
8136
8397
|
const updatePosition = () => {
|
|
8137
8398
|
if (!anchorRef?.current) return;
|
|
@@ -8148,7 +8409,7 @@ var ResourcePicker = (0, import_react25.memo)(function ResourcePicker2({
|
|
|
8148
8409
|
window.addEventListener("resize", updatePosition);
|
|
8149
8410
|
return () => window.removeEventListener("resize", updatePosition);
|
|
8150
8411
|
}, [isOpen, anchorRef]);
|
|
8151
|
-
(0,
|
|
8412
|
+
(0, import_react26.useEffect)(() => {
|
|
8152
8413
|
if (!isOpen) return;
|
|
8153
8414
|
const handleClickOutside = (e) => {
|
|
8154
8415
|
if (pickerRef.current && !pickerRef.current.contains(e.target)) {
|
|
@@ -8161,17 +8422,17 @@ var ResourcePicker = (0, import_react25.memo)(function ResourcePicker2({
|
|
|
8161
8422
|
document.addEventListener("mousedown", handleClickOutside);
|
|
8162
8423
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
8163
8424
|
}, [isOpen, onClose, anchorRef]);
|
|
8164
|
-
(0,
|
|
8425
|
+
(0, import_react26.useEffect)(() => {
|
|
8165
8426
|
if (selectedProviderId && searchInputRef.current) {
|
|
8166
8427
|
searchInputRef.current.focus();
|
|
8167
8428
|
}
|
|
8168
8429
|
}, [selectedProviderId]);
|
|
8169
|
-
(0,
|
|
8430
|
+
(0, import_react26.useEffect)(() => {
|
|
8170
8431
|
if (isOpen) {
|
|
8171
8432
|
scrollRestoredRef.current = null;
|
|
8172
8433
|
}
|
|
8173
8434
|
}, [isOpen]);
|
|
8174
|
-
(0,
|
|
8435
|
+
(0, import_react26.useEffect)(() => {
|
|
8175
8436
|
if (!isOpen || !selectedProviderId || !listRef.current || resources.length === 0) return;
|
|
8176
8437
|
if (scrollRestoredRef.current === selectedProviderId) return;
|
|
8177
8438
|
const savedScroll = sessionStorage.getItem(getScrollKey(selectedProviderId));
|
|
@@ -8185,12 +8446,12 @@ var ResourcePicker = (0, import_react25.memo)(function ResourcePicker2({
|
|
|
8185
8446
|
}
|
|
8186
8447
|
scrollRestoredRef.current = selectedProviderId;
|
|
8187
8448
|
}, [isOpen, selectedProviderId, resources.length]);
|
|
8188
|
-
const handleListScroll = (0,
|
|
8449
|
+
const handleListScroll = (0, import_react26.useCallback)((e) => {
|
|
8189
8450
|
if (!selectedProviderId) return;
|
|
8190
8451
|
const scrollTop = e.currentTarget.scrollTop;
|
|
8191
8452
|
sessionStorage.setItem(getScrollKey(selectedProviderId), String(scrollTop));
|
|
8192
8453
|
}, [selectedProviderId]);
|
|
8193
|
-
(0,
|
|
8454
|
+
(0, import_react26.useEffect)(() => {
|
|
8194
8455
|
if (!isOpen) return;
|
|
8195
8456
|
const handleKeyDown = (e) => {
|
|
8196
8457
|
if (e.key === "Escape") {
|
|
@@ -8201,7 +8462,7 @@ var ResourcePicker = (0, import_react25.memo)(function ResourcePicker2({
|
|
|
8201
8462
|
document.addEventListener("keydown", handleKeyDown);
|
|
8202
8463
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
8203
8464
|
}, [isOpen, onClose]);
|
|
8204
|
-
(0,
|
|
8465
|
+
(0, import_react26.useEffect)(() => {
|
|
8205
8466
|
if (!sentinelRef.current || !hasMore || isLoadingResources) return;
|
|
8206
8467
|
const observer = new IntersectionObserver(
|
|
8207
8468
|
(entries) => {
|
|
@@ -8214,13 +8475,13 @@ var ResourcePicker = (0, import_react25.memo)(function ResourcePicker2({
|
|
|
8214
8475
|
observer.observe(sentinelRef.current);
|
|
8215
8476
|
return () => observer.disconnect();
|
|
8216
8477
|
}, [hasMore, isLoadingResources, onLoadMore]);
|
|
8217
|
-
const handleTabClick = (0,
|
|
8478
|
+
const handleTabClick = (0, import_react26.useCallback)((providerId) => {
|
|
8218
8479
|
if (providerId !== selectedProviderId) {
|
|
8219
8480
|
onSearchChange("");
|
|
8220
8481
|
onSelectProvider(providerId);
|
|
8221
8482
|
}
|
|
8222
8483
|
}, [selectedProviderId, onSelectProvider, onSearchChange]);
|
|
8223
|
-
const handleResourceClick = (0,
|
|
8484
|
+
const handleResourceClick = (0, import_react26.useCallback)((item) => {
|
|
8224
8485
|
onAttachResource(item);
|
|
8225
8486
|
}, [onAttachResource]);
|
|
8226
8487
|
if (!isOpen) return null;
|
|
@@ -8481,7 +8742,7 @@ var STRINGS2 = {
|
|
|
8481
8742
|
uploadImage: "\u4E0A\u4F20\u56FE\u7247"
|
|
8482
8743
|
}
|
|
8483
8744
|
};
|
|
8484
|
-
var AddResourceButton = (0,
|
|
8745
|
+
var AddResourceButton = (0, import_react27.memo)(function AddResourceButton2({
|
|
8485
8746
|
providers,
|
|
8486
8747
|
isLoadingProviders,
|
|
8487
8748
|
onUploadFile,
|
|
@@ -8502,11 +8763,11 @@ var AddResourceButton = (0, import_react26.memo)(function AddResourceButton2({
|
|
|
8502
8763
|
themeClass = ""
|
|
8503
8764
|
}) {
|
|
8504
8765
|
const strings = STRINGS2[locale];
|
|
8505
|
-
const [isMenuOpen, setIsMenuOpen] = (0,
|
|
8506
|
-
const [isPickerOpen, setIsPickerOpen] = (0,
|
|
8507
|
-
const buttonRef = (0,
|
|
8508
|
-
const menuRef = (0,
|
|
8509
|
-
(0,
|
|
8766
|
+
const [isMenuOpen, setIsMenuOpen] = (0, import_react27.useState)(false);
|
|
8767
|
+
const [isPickerOpen, setIsPickerOpen] = (0, import_react27.useState)(false);
|
|
8768
|
+
const buttonRef = (0, import_react27.useRef)(null);
|
|
8769
|
+
const menuRef = (0, import_react27.useRef)(null);
|
|
8770
|
+
(0, import_react27.useEffect)(() => {
|
|
8510
8771
|
if (!isMenuOpen) return;
|
|
8511
8772
|
const handleClickOutside = (e) => {
|
|
8512
8773
|
if (menuRef.current && !menuRef.current.contains(e.target) && buttonRef.current && !buttonRef.current.contains(e.target)) {
|
|
@@ -8516,7 +8777,7 @@ var AddResourceButton = (0, import_react26.memo)(function AddResourceButton2({
|
|
|
8516
8777
|
document.addEventListener("mousedown", handleClickOutside);
|
|
8517
8778
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
8518
8779
|
}, [isMenuOpen]);
|
|
8519
|
-
(0,
|
|
8780
|
+
(0, import_react27.useEffect)(() => {
|
|
8520
8781
|
if (!isMenuOpen) return;
|
|
8521
8782
|
const handleKeyDown = (e) => {
|
|
8522
8783
|
if (e.key === "Escape") {
|
|
@@ -8526,7 +8787,7 @@ var AddResourceButton = (0, import_react26.memo)(function AddResourceButton2({
|
|
|
8526
8787
|
document.addEventListener("keydown", handleKeyDown);
|
|
8527
8788
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
8528
8789
|
}, [isMenuOpen]);
|
|
8529
|
-
const handleButtonClick = (0,
|
|
8790
|
+
const handleButtonClick = (0, import_react27.useCallback)(() => {
|
|
8530
8791
|
if (isPickerOpen) {
|
|
8531
8792
|
setIsPickerOpen(false);
|
|
8532
8793
|
onSelectProvider(null);
|
|
@@ -8540,31 +8801,31 @@ var AddResourceButton = (0, import_react26.memo)(function AddResourceButton2({
|
|
|
8540
8801
|
}
|
|
8541
8802
|
setIsMenuOpen(!isMenuOpen);
|
|
8542
8803
|
}, [isMenuOpen, isPickerOpen, onSelectProvider, providers, onUploadFile, onUploadImage]);
|
|
8543
|
-
const handleUploadFile = (0,
|
|
8804
|
+
const handleUploadFile = (0, import_react27.useCallback)(() => {
|
|
8544
8805
|
setIsMenuOpen(false);
|
|
8545
8806
|
onUploadFile?.();
|
|
8546
8807
|
}, [onUploadFile]);
|
|
8547
|
-
const handleUploadImage = (0,
|
|
8808
|
+
const handleUploadImage = (0, import_react27.useCallback)(() => {
|
|
8548
8809
|
setIsMenuOpen(false);
|
|
8549
8810
|
onUploadImage?.();
|
|
8550
8811
|
}, [onUploadImage]);
|
|
8551
|
-
const handleProviderClick = (0,
|
|
8812
|
+
const handleProviderClick = (0, import_react27.useCallback)((providerId) => {
|
|
8552
8813
|
setIsMenuOpen(false);
|
|
8553
8814
|
onSelectProvider(providerId);
|
|
8554
8815
|
setIsPickerOpen(true);
|
|
8555
8816
|
}, [onSelectProvider]);
|
|
8556
|
-
const handlePickerClose = (0,
|
|
8817
|
+
const handlePickerClose = (0, import_react27.useCallback)(() => {
|
|
8557
8818
|
setIsPickerOpen(false);
|
|
8558
8819
|
onSelectProvider(null);
|
|
8559
8820
|
}, [onSelectProvider]);
|
|
8560
|
-
const handlePickerSelectProvider = (0,
|
|
8821
|
+
const handlePickerSelectProvider = (0, import_react27.useCallback)((providerId) => {
|
|
8561
8822
|
if (providerId === null) {
|
|
8562
8823
|
setIsPickerOpen(false);
|
|
8563
8824
|
setIsMenuOpen(true);
|
|
8564
8825
|
}
|
|
8565
8826
|
onSelectProvider(providerId);
|
|
8566
8827
|
}, [onSelectProvider]);
|
|
8567
|
-
const handleAttachResource = (0,
|
|
8828
|
+
const handleAttachResource = (0, import_react27.useCallback)((item) => {
|
|
8568
8829
|
onAttachResource(item);
|
|
8569
8830
|
setIsPickerOpen(false);
|
|
8570
8831
|
onSelectProvider(null);
|
|
@@ -8718,9 +8979,9 @@ var addResourceButtonStyles = `
|
|
|
8718
8979
|
`;
|
|
8719
8980
|
|
|
8720
8981
|
// src/renderer/components/AttachedResourceTags.tsx
|
|
8721
|
-
var
|
|
8982
|
+
var import_react28 = require("react");
|
|
8722
8983
|
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
8723
|
-
var AttachedResourceTags = (0,
|
|
8984
|
+
var AttachedResourceTags = (0, import_react28.memo)(function AttachedResourceTags2({
|
|
8724
8985
|
resources,
|
|
8725
8986
|
onRemove,
|
|
8726
8987
|
disabled
|
|
@@ -8799,7 +9060,7 @@ var attachedResourceTagsStyles = `
|
|
|
8799
9060
|
|
|
8800
9061
|
// src/renderer/components/SanqianChat.tsx
|
|
8801
9062
|
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
8802
|
-
var SanqianChat = (0,
|
|
9063
|
+
var SanqianChat = (0, import_react29.memo)(function SanqianChat2({
|
|
8803
9064
|
adapter,
|
|
8804
9065
|
placeholder,
|
|
8805
9066
|
autoConnect = true,
|
|
@@ -8811,22 +9072,22 @@ var SanqianChat = (0, import_react28.memo)(function SanqianChat2({
|
|
|
8811
9072
|
config,
|
|
8812
9073
|
logo
|
|
8813
9074
|
}) {
|
|
8814
|
-
const chatContainerRef = (0,
|
|
8815
|
-
const chatInputRef = (0,
|
|
8816
|
-
const messageListRef = (0,
|
|
8817
|
-
const onStateChangeRef = (0,
|
|
8818
|
-
(0,
|
|
9075
|
+
const chatContainerRef = (0, import_react29.useRef)(null);
|
|
9076
|
+
const chatInputRef = (0, import_react29.useRef)(null);
|
|
9077
|
+
const messageListRef = (0, import_react29.useRef)(null);
|
|
9078
|
+
const onStateChangeRef = (0, import_react29.useRef)(onStateChange);
|
|
9079
|
+
(0, import_react29.useEffect)(() => {
|
|
8819
9080
|
onStateChangeRef.current = onStateChange;
|
|
8820
9081
|
}, [onStateChange]);
|
|
8821
9082
|
const resolvedConfig = useResolvedUiConfig(config);
|
|
8822
9083
|
const { themeClass, isDarkMode } = useResolvedTheme(resolvedConfig?.theme ?? "auto");
|
|
8823
9084
|
const accentStyle = useAccentStyle(resolvedConfig?.accentColor);
|
|
8824
9085
|
const resolvedLogo = logo ?? resolvedConfig?.logo;
|
|
8825
|
-
const strings = (0,
|
|
9086
|
+
const strings = (0, import_react29.useMemo)(
|
|
8826
9087
|
() => resolveChatStrings(resolvedConfig?.locale, resolvedConfig?.strings),
|
|
8827
9088
|
[resolvedConfig?.locale, resolvedConfig?.strings]
|
|
8828
9089
|
);
|
|
8829
|
-
const headerConfig = (0,
|
|
9090
|
+
const headerConfig = (0, import_react29.useMemo)(
|
|
8830
9091
|
() => {
|
|
8831
9092
|
if (!resolvedConfig) {
|
|
8832
9093
|
return resolvedLogo ? { logo: resolvedLogo } : void 0;
|
|
@@ -8839,7 +9100,7 @@ var SanqianChat = (0, import_react28.memo)(function SanqianChat2({
|
|
|
8839
9100
|
[resolvedConfig, resolvedLogo]
|
|
8840
9101
|
);
|
|
8841
9102
|
const { logoNode, showPin, showClose, isPinned, togglePin, resolvedOnClose } = useChatHeader(headerConfig);
|
|
8842
|
-
const emptyLogoNode = (0,
|
|
9103
|
+
const emptyLogoNode = (0, import_react29.useMemo)(() => resolveLogoNode(resolvedLogo, "empty"), [resolvedLogo]);
|
|
8843
9104
|
const showHeader = !!(logoNode || showClose || showPin);
|
|
8844
9105
|
useChatStyles();
|
|
8845
9106
|
useConnection({ adapter, autoConnect });
|
|
@@ -8849,7 +9110,7 @@ var SanqianChat = (0, import_react28.memo)(function SanqianChat2({
|
|
|
8849
9110
|
onConversationChange
|
|
8850
9111
|
});
|
|
8851
9112
|
const resourcePicker = useResourcePicker({ adapter });
|
|
8852
|
-
const resourceProviders = (0,
|
|
9113
|
+
const resourceProviders = (0, import_react29.useMemo)(
|
|
8853
9114
|
() => resourcePicker.providers.filter((p) => p.hasGetList),
|
|
8854
9115
|
[resourcePicker.providers]
|
|
8855
9116
|
);
|
|
@@ -8865,13 +9126,17 @@ var SanqianChat = (0, import_react28.memo)(function SanqianChat2({
|
|
|
8865
9126
|
chat.submitHitlInput({ cancelled: true });
|
|
8866
9127
|
}
|
|
8867
9128
|
};
|
|
8868
|
-
const handleSendMessage = (0,
|
|
8869
|
-
|
|
8870
|
-
|
|
9129
|
+
const handleSendMessage = (0, import_react29.useCallback)(async (content) => {
|
|
9130
|
+
const attachedResources = resourcePicker.attachedResources.length > 0 ? [...resourcePicker.attachedResources] : void 0;
|
|
9131
|
+
const sent = await chat.trySendMessage(content, {
|
|
9132
|
+
attachedResources
|
|
8871
9133
|
});
|
|
8872
|
-
|
|
9134
|
+
if (sent) {
|
|
9135
|
+
resourcePicker.clearAttachedResources();
|
|
9136
|
+
}
|
|
9137
|
+
return sent;
|
|
8873
9138
|
}, [chat, resourcePicker]);
|
|
8874
|
-
(0,
|
|
9139
|
+
(0, import_react29.useEffect)(() => {
|
|
8875
9140
|
onStateChangeRef.current?.({
|
|
8876
9141
|
messages: chat.messages,
|
|
8877
9142
|
conversationId: chat.conversationId
|
|
@@ -8987,6 +9252,7 @@ var SanqianChat = (0, import_react28.memo)(function SanqianChat2({
|
|
|
8987
9252
|
stopLabel: strings.inputStop,
|
|
8988
9253
|
isStreaming: chat.isStreaming,
|
|
8989
9254
|
isLoading: chat.isLoading,
|
|
9255
|
+
allowEmptySubmit: resourcePicker.attachedResources.length > 0 || chat.sessionResources.length > 0,
|
|
8990
9256
|
disabled: !!chat.pendingInterrupt || chat.isLoading && !chat.isStreaming,
|
|
8991
9257
|
leftSlot: resourceProviders.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
8992
9258
|
AddResourceButton,
|
|
@@ -9017,17 +9283,17 @@ var SanqianChat = (0, import_react28.memo)(function SanqianChat2({
|
|
|
9017
9283
|
});
|
|
9018
9284
|
|
|
9019
9285
|
// src/renderer/components/FloatingChat.tsx
|
|
9020
|
-
var
|
|
9286
|
+
var import_react35 = require("react");
|
|
9021
9287
|
|
|
9022
9288
|
// src/renderer/components/ModeToggleButton.tsx
|
|
9023
|
-
var
|
|
9289
|
+
var import_react30 = require("react");
|
|
9024
9290
|
var import_jsx_runtime18 = (
|
|
9025
9291
|
// Float out icon - two overlapping panels (macOS style)
|
|
9026
9292
|
require("react/jsx-runtime")
|
|
9027
9293
|
);
|
|
9028
9294
|
function ModeToggleButton({ className, locale = "en" }) {
|
|
9029
9295
|
const { isEmbedded, toggleMode } = useChatPanel();
|
|
9030
|
-
const strings = (0,
|
|
9296
|
+
const strings = (0, import_react30.useMemo)(() => resolveChatStrings(locale), [locale]);
|
|
9031
9297
|
const handleClick = async () => {
|
|
9032
9298
|
await toggleMode();
|
|
9033
9299
|
};
|
|
@@ -9056,7 +9322,7 @@ function ModeToggleButton({ className, locale = "en" }) {
|
|
|
9056
9322
|
}
|
|
9057
9323
|
|
|
9058
9324
|
// src/renderer/components/AttachButton.tsx
|
|
9059
|
-
var
|
|
9325
|
+
var import_react31 = require("react");
|
|
9060
9326
|
var import_jsx_runtime19 = (
|
|
9061
9327
|
// Attached state: filled icon
|
|
9062
9328
|
require("react/jsx-runtime")
|
|
@@ -9064,7 +9330,7 @@ var import_jsx_runtime19 = (
|
|
|
9064
9330
|
function AttachButton({ className, locale = "en" }) {
|
|
9065
9331
|
const { isAttached, isAvailable, toggle } = useAttachState();
|
|
9066
9332
|
const { isFloating } = useChatPanel();
|
|
9067
|
-
const strings = (0,
|
|
9333
|
+
const strings = (0, import_react31.useMemo)(() => resolveChatStrings(locale), [locale]);
|
|
9068
9334
|
if (!isFloating || !isAvailable) return null;
|
|
9069
9335
|
const handleClick = async () => {
|
|
9070
9336
|
await toggle();
|
|
@@ -9094,16 +9360,16 @@ function AttachButton({ className, locale = "en" }) {
|
|
|
9094
9360
|
}
|
|
9095
9361
|
|
|
9096
9362
|
// src/renderer/components/Resizer.tsx
|
|
9097
|
-
var
|
|
9363
|
+
var import_react32 = require("react");
|
|
9098
9364
|
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
9099
9365
|
function useRafThrottle(fn) {
|
|
9100
|
-
const rafRef = (0,
|
|
9101
|
-
const argsRef = (0,
|
|
9102
|
-
const fnRef = (0,
|
|
9103
|
-
(0,
|
|
9366
|
+
const rafRef = (0, import_react32.useRef)(null);
|
|
9367
|
+
const argsRef = (0, import_react32.useRef)(null);
|
|
9368
|
+
const fnRef = (0, import_react32.useRef)(fn);
|
|
9369
|
+
(0, import_react32.useLayoutEffect)(() => {
|
|
9104
9370
|
fnRef.current = fn;
|
|
9105
9371
|
});
|
|
9106
|
-
const throttledFn = (0,
|
|
9372
|
+
const throttledFn = (0, import_react32.useCallback)((...args) => {
|
|
9107
9373
|
argsRef.current = args;
|
|
9108
9374
|
if (rafRef.current === null) {
|
|
9109
9375
|
rafRef.current = requestAnimationFrame(() => {
|
|
@@ -9114,7 +9380,7 @@ function useRafThrottle(fn) {
|
|
|
9114
9380
|
});
|
|
9115
9381
|
}
|
|
9116
9382
|
}, []);
|
|
9117
|
-
(0,
|
|
9383
|
+
(0, import_react32.useEffect)(() => {
|
|
9118
9384
|
return () => {
|
|
9119
9385
|
if (rafRef.current !== null) {
|
|
9120
9386
|
cancelAnimationFrame(rafRef.current);
|
|
@@ -9132,19 +9398,19 @@ function Resizer({
|
|
|
9132
9398
|
className = ""
|
|
9133
9399
|
}) {
|
|
9134
9400
|
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,
|
|
9401
|
+
const [isHovered, setIsHovered] = (0, import_react32.useState)(false);
|
|
9402
|
+
const [isDragging, setIsDragging] = (0, import_react32.useState)(false);
|
|
9403
|
+
const startX = (0, import_react32.useRef)(0);
|
|
9404
|
+
const startWidth = (0, import_react32.useRef)(0);
|
|
9405
|
+
const widthRef = (0, import_react32.useRef)(width);
|
|
9406
|
+
(0, import_react32.useLayoutEffect)(() => {
|
|
9141
9407
|
widthRef.current = width;
|
|
9142
9408
|
}, [width]);
|
|
9143
9409
|
const throttledSetWidth = useRafThrottle(setWidth);
|
|
9144
|
-
const handleDoubleClick = (0,
|
|
9410
|
+
const handleDoubleClick = (0, import_react32.useCallback)(() => {
|
|
9145
9411
|
setWidth(defaultWidth, true);
|
|
9146
9412
|
}, [defaultWidth, setWidth]);
|
|
9147
|
-
const handleMouseDown = (0,
|
|
9413
|
+
const handleMouseDown = (0, import_react32.useCallback)((e) => {
|
|
9148
9414
|
e.preventDefault();
|
|
9149
9415
|
setIsDragging(true);
|
|
9150
9416
|
startX.current = e.screenX;
|
|
@@ -9152,7 +9418,7 @@ function Resizer({
|
|
|
9152
9418
|
document.body.style.cursor = "col-resize";
|
|
9153
9419
|
document.body.style.userSelect = "none";
|
|
9154
9420
|
}, []);
|
|
9155
|
-
(0,
|
|
9421
|
+
(0, import_react32.useEffect)(() => {
|
|
9156
9422
|
if (!isDragging) return;
|
|
9157
9423
|
const handleMouseMove = (e) => {
|
|
9158
9424
|
const deltaX = e.screenX - startX.current;
|
|
@@ -9229,15 +9495,15 @@ function Resizer({
|
|
|
9229
9495
|
}
|
|
9230
9496
|
|
|
9231
9497
|
// src/renderer/components/ResourceChip.tsx
|
|
9232
|
-
var
|
|
9498
|
+
var import_react33 = require("react");
|
|
9233
9499
|
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
9234
|
-
var ResourceChip = (0,
|
|
9500
|
+
var ResourceChip = (0, import_react33.memo)(function ResourceChip2({
|
|
9235
9501
|
resource,
|
|
9236
9502
|
onRemove,
|
|
9237
9503
|
disabled,
|
|
9238
9504
|
locale: localeProp
|
|
9239
9505
|
}) {
|
|
9240
|
-
const i18nContext = (0,
|
|
9506
|
+
const i18nContext = (0, import_react33.useContext)(I18nContext);
|
|
9241
9507
|
const locale = i18nContext?.locale ?? localeProp ?? "en";
|
|
9242
9508
|
const strings = resolveChatStrings(locale);
|
|
9243
9509
|
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: `resource-chip ${disabled ? "disabled" : ""}`, children: [
|
|
@@ -9256,7 +9522,7 @@ var ResourceChip = (0, import_react32.memo)(function ResourceChip2({
|
|
|
9256
9522
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("style", { children: resourceChipStyles })
|
|
9257
9523
|
] });
|
|
9258
9524
|
});
|
|
9259
|
-
var ResourceChipList = (0,
|
|
9525
|
+
var ResourceChipList = (0, import_react33.memo)(function ResourceChipList2({
|
|
9260
9526
|
resources,
|
|
9261
9527
|
onRemove,
|
|
9262
9528
|
disabled
|
|
@@ -9335,7 +9601,7 @@ var resourceChipStyles = `
|
|
|
9335
9601
|
`;
|
|
9336
9602
|
|
|
9337
9603
|
// src/renderer/hooks/useWindowBackgroundSync.ts
|
|
9338
|
-
var
|
|
9604
|
+
var import_react34 = require("react");
|
|
9339
9605
|
var cachedPlatform = null;
|
|
9340
9606
|
var getPlatform = () => {
|
|
9341
9607
|
if (cachedPlatform !== null) return cachedPlatform;
|
|
@@ -9353,7 +9619,7 @@ var setBackgroundColor = (color) => {
|
|
|
9353
9619
|
}
|
|
9354
9620
|
};
|
|
9355
9621
|
function useWindowBackgroundSync(isDarkMode) {
|
|
9356
|
-
(0,
|
|
9622
|
+
(0, import_react34.useEffect)(() => {
|
|
9357
9623
|
if (getPlatform() !== "win32") return;
|
|
9358
9624
|
const colors = getBaseColors(isDarkMode);
|
|
9359
9625
|
setBackgroundColor(colors.bg);
|
|
@@ -9362,7 +9628,7 @@ function useWindowBackgroundSync(isDarkMode) {
|
|
|
9362
9628
|
|
|
9363
9629
|
// src/renderer/components/FloatingChat.tsx
|
|
9364
9630
|
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
9365
|
-
var FloatingChat = (0,
|
|
9631
|
+
var FloatingChat = (0, import_react35.memo)(function FloatingChat2({
|
|
9366
9632
|
messages,
|
|
9367
9633
|
isLoading,
|
|
9368
9634
|
isStreaming,
|
|
@@ -9385,8 +9651,8 @@ var FloatingChat = (0, import_react34.memo)(function FloatingChat2({
|
|
|
9385
9651
|
header,
|
|
9386
9652
|
footer
|
|
9387
9653
|
}) {
|
|
9388
|
-
const chatContainerRef = (0,
|
|
9389
|
-
const chatInputRef = (0,
|
|
9654
|
+
const chatContainerRef = (0, import_react35.useRef)(null);
|
|
9655
|
+
const chatInputRef = (0, import_react35.useRef)(null);
|
|
9390
9656
|
useChatStyles();
|
|
9391
9657
|
useFocusPersistence({
|
|
9392
9658
|
containerRef: chatContainerRef,
|
|
@@ -9398,18 +9664,18 @@ var FloatingChat = (0, import_react34.memo)(function FloatingChat2({
|
|
|
9398
9664
|
const { themeClass, isDarkMode } = useResolvedTheme(themeMode);
|
|
9399
9665
|
const accentStyle = useAccentStyle(resolvedConfig?.accentColor);
|
|
9400
9666
|
useWindowBackgroundSync(isDarkMode);
|
|
9401
|
-
const rootStyle = (0,
|
|
9667
|
+
const rootStyle = (0, import_react35.useMemo)(() => ({
|
|
9402
9668
|
...accentStyle || {},
|
|
9403
9669
|
minHeight: "100vh",
|
|
9404
9670
|
minWidth: "100vw"
|
|
9405
9671
|
}), [accentStyle]);
|
|
9406
9672
|
const resolvedLogo = logo ?? resolvedConfig?.logo;
|
|
9407
9673
|
const resolvedLocale = resolvedConfig?.locale ?? locale;
|
|
9408
|
-
const resolvedStrings = (0,
|
|
9674
|
+
const resolvedStrings = (0, import_react35.useMemo)(
|
|
9409
9675
|
() => resolveChatStrings(resolvedLocale, resolvedConfig?.strings),
|
|
9410
9676
|
[resolvedLocale, resolvedConfig?.strings]
|
|
9411
9677
|
);
|
|
9412
|
-
const headerConfig = (0,
|
|
9678
|
+
const headerConfig = (0, import_react35.useMemo)(
|
|
9413
9679
|
() => {
|
|
9414
9680
|
if (!resolvedConfig) {
|
|
9415
9681
|
return resolvedLogo ? { logo: resolvedLogo } : void 0;
|
|
@@ -9422,7 +9688,7 @@ var FloatingChat = (0, import_react34.memo)(function FloatingChat2({
|
|
|
9422
9688
|
[resolvedConfig, resolvedLogo]
|
|
9423
9689
|
);
|
|
9424
9690
|
const { logoNode, showPin, showClose, isPinned, togglePin, resolvedOnClose } = useChatHeader(headerConfig);
|
|
9425
|
-
const emptyLogoNode = (0,
|
|
9691
|
+
const emptyLogoNode = (0, import_react35.useMemo)(() => resolveLogoNode(resolvedLogo, "empty"), [resolvedLogo]);
|
|
9426
9692
|
const inputPlaceholder = placeholder ?? resolvedStrings.inputPlaceholder;
|
|
9427
9693
|
const showHeader = !!(header || logoNode || showPin || showClose);
|
|
9428
9694
|
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 +9733,7 @@ var FloatingChat = (0, import_react34.memo)(function FloatingChat2({
|
|
|
9467
9733
|
] })
|
|
9468
9734
|
] });
|
|
9469
9735
|
const resolvedHeader = header ?? (showHeader ? defaultHeader : null);
|
|
9470
|
-
const defaultRenderMessage = (0,
|
|
9736
|
+
const defaultRenderMessage = (0, import_react35.useCallback)(
|
|
9471
9737
|
(message) => {
|
|
9472
9738
|
if (message.role === "tool") return null;
|
|
9473
9739
|
const isUser = message.role === "user";
|
|
@@ -9481,7 +9747,7 @@ var FloatingChat = (0, import_react34.memo)(function FloatingChat2({
|
|
|
9481
9747
|
},
|
|
9482
9748
|
[renderContent]
|
|
9483
9749
|
);
|
|
9484
|
-
const defaultRenderHitl = (0,
|
|
9750
|
+
const defaultRenderHitl = (0, import_react35.useCallback)(
|
|
9485
9751
|
(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
9752
|
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "font-medium mb-2", children: interrupt.type === "approval_request" ? resolvedStrings.hitlApprovalRequired : resolvedStrings.hitlInputRequired }),
|
|
9487
9753
|
interrupt.tool && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("p", { className: "text-sm mb-2", children: [
|
|
@@ -9562,6 +9828,7 @@ var FloatingChat = (0, import_react34.memo)(function FloatingChat2({
|
|
|
9562
9828
|
stopLabel: resolvedStrings.inputStop,
|
|
9563
9829
|
isStreaming,
|
|
9564
9830
|
isLoading,
|
|
9831
|
+
allowEmptySubmit: !!sessionResources && sessionResources.length > 0,
|
|
9565
9832
|
disabled: !!pendingInterrupt || isLoading && !isStreaming,
|
|
9566
9833
|
autoFocus: true
|
|
9567
9834
|
}
|
|
@@ -9571,10 +9838,10 @@ var FloatingChat = (0, import_react34.memo)(function FloatingChat2({
|
|
|
9571
9838
|
});
|
|
9572
9839
|
|
|
9573
9840
|
// src/renderer/components/HistoryList.tsx
|
|
9574
|
-
var
|
|
9841
|
+
var import_react36 = require("react");
|
|
9575
9842
|
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
9576
9843
|
function DeleteButton({ onClick, title, colors }) {
|
|
9577
|
-
const [isHovered, setIsHovered] = (0,
|
|
9844
|
+
const [isHovered, setIsHovered] = (0, import_react36.useState)(false);
|
|
9578
9845
|
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
9579
9846
|
"button",
|
|
9580
9847
|
{
|
|
@@ -9618,7 +9885,7 @@ function DeleteButton({ onClick, title, colors }) {
|
|
|
9618
9885
|
);
|
|
9619
9886
|
}
|
|
9620
9887
|
function LoadMoreButton({ onClick, colors, children }) {
|
|
9621
|
-
const [isHovered, setIsHovered] = (0,
|
|
9888
|
+
const [isHovered, setIsHovered] = (0, import_react36.useState)(false);
|
|
9622
9889
|
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
9623
9890
|
"button",
|
|
9624
9891
|
{
|
|
@@ -9668,7 +9935,7 @@ function formatRelativeTime(dateStr, strings) {
|
|
|
9668
9935
|
return date.toLocaleDateString(void 0, { month: "short", day: "numeric" });
|
|
9669
9936
|
}
|
|
9670
9937
|
}
|
|
9671
|
-
var HistoryList = (0,
|
|
9938
|
+
var HistoryList = (0, import_react36.memo)(function HistoryList2({
|
|
9672
9939
|
conversations,
|
|
9673
9940
|
selectedId,
|
|
9674
9941
|
isLoading,
|
|
@@ -9680,13 +9947,13 @@ var HistoryList = (0, import_react35.memo)(function HistoryList2({
|
|
|
9680
9947
|
isDarkMode = false,
|
|
9681
9948
|
strings = {}
|
|
9682
9949
|
}) {
|
|
9683
|
-
const [hoveredId, setHoveredId] = (0,
|
|
9684
|
-
const loadMoreRef = (0,
|
|
9685
|
-
const isLoadingRef = (0,
|
|
9686
|
-
(0,
|
|
9950
|
+
const [hoveredId, setHoveredId] = (0, import_react36.useState)(null);
|
|
9951
|
+
const loadMoreRef = (0, import_react36.useRef)(null);
|
|
9952
|
+
const isLoadingRef = (0, import_react36.useRef)(isLoading);
|
|
9953
|
+
(0, import_react36.useEffect)(() => {
|
|
9687
9954
|
isLoadingRef.current = isLoading;
|
|
9688
9955
|
}, [isLoading]);
|
|
9689
|
-
(0,
|
|
9956
|
+
(0, import_react36.useEffect)(() => {
|
|
9690
9957
|
if (!hasMore || loadError || !onLoadMore) return;
|
|
9691
9958
|
const sentinel = loadMoreRef.current;
|
|
9692
9959
|
if (!sentinel) return;
|
|
@@ -9783,10 +10050,10 @@ var HistoryList = (0, import_react35.memo)(function HistoryList2({
|
|
|
9783
10050
|
});
|
|
9784
10051
|
|
|
9785
10052
|
// src/renderer/components/HistoryModal.tsx
|
|
9786
|
-
var
|
|
10053
|
+
var import_react37 = require("react");
|
|
9787
10054
|
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
9788
10055
|
var ANIMATION_DURATION = 120;
|
|
9789
|
-
var HistoryModal = (0,
|
|
10056
|
+
var HistoryModal = (0, import_react37.memo)(function HistoryModal2({
|
|
9790
10057
|
isOpen,
|
|
9791
10058
|
onClose,
|
|
9792
10059
|
title,
|
|
@@ -9794,10 +10061,10 @@ var HistoryModal = (0, import_react36.memo)(function HistoryModal2({
|
|
|
9794
10061
|
children,
|
|
9795
10062
|
isDarkMode = false
|
|
9796
10063
|
}) {
|
|
9797
|
-
const modalRef = (0,
|
|
9798
|
-
const [isClosing, setIsClosing] = (0,
|
|
9799
|
-
const [shouldRender, setShouldRender] = (0,
|
|
9800
|
-
(0,
|
|
10064
|
+
const modalRef = (0, import_react37.useRef)(null);
|
|
10065
|
+
const [isClosing, setIsClosing] = (0, import_react37.useState)(false);
|
|
10066
|
+
const [shouldRender, setShouldRender] = (0, import_react37.useState)(isOpen);
|
|
10067
|
+
(0, import_react37.useEffect)(() => {
|
|
9801
10068
|
if (isOpen) {
|
|
9802
10069
|
setShouldRender(true);
|
|
9803
10070
|
setIsClosing(false);
|
|
@@ -9809,7 +10076,7 @@ var HistoryModal = (0, import_react36.memo)(function HistoryModal2({
|
|
|
9809
10076
|
}, ANIMATION_DURATION);
|
|
9810
10077
|
}
|
|
9811
10078
|
}, [isOpen, shouldRender, isClosing]);
|
|
9812
|
-
const handleClose = (0,
|
|
10079
|
+
const handleClose = (0, import_react37.useCallback)(() => {
|
|
9813
10080
|
setIsClosing(true);
|
|
9814
10081
|
setTimeout(() => {
|
|
9815
10082
|
setShouldRender(false);
|
|
@@ -9817,7 +10084,7 @@ var HistoryModal = (0, import_react36.memo)(function HistoryModal2({
|
|
|
9817
10084
|
onClose();
|
|
9818
10085
|
}, ANIMATION_DURATION);
|
|
9819
10086
|
}, [onClose]);
|
|
9820
|
-
(0,
|
|
10087
|
+
(0, import_react37.useEffect)(() => {
|
|
9821
10088
|
if (!shouldRender || isClosing) return;
|
|
9822
10089
|
const handleKeyDown = (e) => {
|
|
9823
10090
|
if (e.key === "Escape") {
|
|
@@ -9828,11 +10095,11 @@ var HistoryModal = (0, import_react36.memo)(function HistoryModal2({
|
|
|
9828
10095
|
document.addEventListener("keydown", handleKeyDown);
|
|
9829
10096
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
9830
10097
|
}, [shouldRender, isClosing, handleClose]);
|
|
9831
|
-
(0,
|
|
10098
|
+
(0, import_react37.useEffect)(() => {
|
|
9832
10099
|
if (!isOpen || !modalRef.current) return;
|
|
9833
10100
|
modalRef.current.focus();
|
|
9834
10101
|
}, [isOpen]);
|
|
9835
|
-
const handleBackdropClick = (0,
|
|
10102
|
+
const handleBackdropClick = (0, import_react37.useCallback)(
|
|
9836
10103
|
(e) => {
|
|
9837
10104
|
if (e.target === e.currentTarget && !isClosing) {
|
|
9838
10105
|
handleClose();
|
|
@@ -9971,7 +10238,7 @@ var HistoryModal = (0, import_react36.memo)(function HistoryModal2({
|
|
|
9971
10238
|
});
|
|
9972
10239
|
|
|
9973
10240
|
// src/renderer/components/CompactChat.tsx
|
|
9974
|
-
var
|
|
10241
|
+
var import_react38 = require("react");
|
|
9975
10242
|
var import_react_dom = require("react-dom");
|
|
9976
10243
|
|
|
9977
10244
|
// src/renderer/components/PanelControls.tsx
|
|
@@ -10011,7 +10278,7 @@ var PanelControls = {
|
|
|
10011
10278
|
|
|
10012
10279
|
// src/renderer/components/CompactChat.tsx
|
|
10013
10280
|
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
10014
|
-
var CompactChat = (0,
|
|
10281
|
+
var CompactChat = (0, import_react38.memo)(function CompactChat2({
|
|
10015
10282
|
adapter,
|
|
10016
10283
|
config,
|
|
10017
10284
|
logo,
|
|
@@ -10047,12 +10314,12 @@ var CompactChat = (0, import_react37.memo)(function CompactChat2({
|
|
|
10047
10314
|
const { themeClass, isDarkMode: resolvedIsDarkMode } = useResolvedTheme(themeMode);
|
|
10048
10315
|
const accentStyle = useAccentStyle(resolvedConfig?.accentColor);
|
|
10049
10316
|
const resolvedLogo = logo ?? resolvedConfig?.logo;
|
|
10050
|
-
const baseStrings = (0,
|
|
10317
|
+
const baseStrings = (0, import_react38.useMemo)(
|
|
10051
10318
|
() => resolveChatStrings(resolvedConfig?.locale, resolvedConfig?.strings),
|
|
10052
10319
|
[resolvedConfig?.locale, resolvedConfig?.strings]
|
|
10053
10320
|
);
|
|
10054
|
-
const mergedStrings = (0,
|
|
10055
|
-
const headerConfig = (0,
|
|
10321
|
+
const mergedStrings = (0, import_react38.useMemo)(() => ({ ...baseStrings, ...strings }), [baseStrings, strings]);
|
|
10322
|
+
const headerConfig = (0, import_react38.useMemo)(
|
|
10056
10323
|
() => {
|
|
10057
10324
|
if (!resolvedConfig) {
|
|
10058
10325
|
return resolvedLogo ? { logo: resolvedLogo } : void 0;
|
|
@@ -10065,13 +10332,14 @@ var CompactChat = (0, import_react37.memo)(function CompactChat2({
|
|
|
10065
10332
|
[resolvedConfig, resolvedLogo]
|
|
10066
10333
|
);
|
|
10067
10334
|
const { logoNode, showPin, showClose, isPinned, togglePin, resolvedOnClose } = useChatHeader(headerConfig);
|
|
10068
|
-
const emptyLogoNode = (0,
|
|
10335
|
+
const emptyLogoNode = (0, import_react38.useMemo)(() => resolveLogoNode(resolvedLogo, "empty"), [resolvedLogo]);
|
|
10069
10336
|
const { isEmbedded, toggleMode, hide: hidePanel } = useChatPanel();
|
|
10070
|
-
const chatContainerRef = (0,
|
|
10071
|
-
const chatInputRef = (0,
|
|
10072
|
-
const [showHistory, setShowHistory] = (0,
|
|
10073
|
-
|
|
10074
|
-
const
|
|
10337
|
+
const chatContainerRef = (0, import_react38.useRef)(null);
|
|
10338
|
+
const chatInputRef = (0, import_react38.useRef)(null);
|
|
10339
|
+
const [showHistory, setShowHistory] = (0, import_react38.useState)(false);
|
|
10340
|
+
useWindowDragLock(showHistory);
|
|
10341
|
+
const [connectionAlert, setConnectionAlert] = (0, import_react38.useState)(null);
|
|
10342
|
+
const portalContainerRef = (0, import_react38.useRef)(inputPortalContainer ?? null);
|
|
10075
10343
|
portalContainerRef.current = inputPortalContainer ?? null;
|
|
10076
10344
|
const shouldRenderInputExternally = !!inputPortalContainer;
|
|
10077
10345
|
const inputPlaceholder = placeholder ?? mergedStrings.inputPlaceholder;
|
|
@@ -10110,49 +10378,55 @@ var CompactChat = (0, import_react37.memo)(function CompactChat2({
|
|
|
10110
10378
|
onError
|
|
10111
10379
|
});
|
|
10112
10380
|
const resourcePicker = useResourcePicker({ adapter });
|
|
10113
|
-
const resourceProviders = (0,
|
|
10381
|
+
const resourceProviders = (0, import_react38.useMemo)(
|
|
10114
10382
|
() => resourcePicker.providers.filter((p) => p.hasGetList),
|
|
10115
10383
|
[resourcePicker.providers]
|
|
10116
10384
|
);
|
|
10117
|
-
const handleHitlCancel = (0,
|
|
10385
|
+
const handleHitlCancel = (0, import_react38.useCallback)(() => {
|
|
10118
10386
|
if (chat.pendingInterrupt?.type === "approval_request") {
|
|
10119
10387
|
chat.rejectHitl();
|
|
10120
10388
|
} else {
|
|
10121
10389
|
chat.submitHitlInput({ cancelled: true });
|
|
10122
10390
|
}
|
|
10123
10391
|
}, [chat.pendingInterrupt?.type, chat.rejectHitl, chat.submitHitlInput]);
|
|
10124
|
-
const handleSendWithResources = (0,
|
|
10125
|
-
const resources = resourcePicker.attachedResources;
|
|
10126
|
-
|
|
10127
|
-
|
|
10128
|
-
|
|
10129
|
-
|
|
10392
|
+
const handleSendWithResources = (0, import_react38.useCallback)(async (content) => {
|
|
10393
|
+
const resources = [...resourcePicker.attachedResources];
|
|
10394
|
+
const sent = await chat.trySendMessage(
|
|
10395
|
+
content,
|
|
10396
|
+
resources.length > 0 ? { attachedResources: resources } : void 0
|
|
10397
|
+
);
|
|
10398
|
+
if (sent) {
|
|
10399
|
+
resourcePicker.clearAttachedResources();
|
|
10400
|
+
}
|
|
10401
|
+
return sent;
|
|
10402
|
+
}, [chat.trySendMessage, resourcePicker.attachedResources, resourcePicker.clearAttachedResources]);
|
|
10403
|
+
(0, import_react38.useEffect)(() => {
|
|
10130
10404
|
if (sendMessageRef) {
|
|
10131
10405
|
sendMessageRef.current = chat.sendMessage;
|
|
10132
10406
|
}
|
|
10133
10407
|
}, [sendMessageRef, chat.sendMessage]);
|
|
10134
|
-
(0,
|
|
10408
|
+
(0, import_react38.useEffect)(() => {
|
|
10135
10409
|
if (newConversationRef) {
|
|
10136
10410
|
newConversationRef.current = chat.newConversation;
|
|
10137
10411
|
}
|
|
10138
10412
|
}, [newConversationRef, chat.newConversation]);
|
|
10139
|
-
(0,
|
|
10413
|
+
(0, import_react38.useEffect)(() => {
|
|
10140
10414
|
if (parentFocusInputRef) {
|
|
10141
10415
|
parentFocusInputRef.current = () => chatInputRef.current?.focus();
|
|
10142
10416
|
}
|
|
10143
10417
|
}, [parentFocusInputRef]);
|
|
10144
|
-
(0,
|
|
10418
|
+
(0, import_react38.useEffect)(() => {
|
|
10145
10419
|
if (parentSetTextRef) {
|
|
10146
10420
|
parentSetTextRef.current = (text) => chatInputRef.current?.setValue(text);
|
|
10147
10421
|
}
|
|
10148
10422
|
}, [parentSetTextRef]);
|
|
10149
|
-
(0,
|
|
10423
|
+
(0, import_react38.useEffect)(() => {
|
|
10150
10424
|
if (!adapter.onFocusInput) return;
|
|
10151
10425
|
return adapter.onFocusInput(() => {
|
|
10152
10426
|
chatInputRef.current?.focus();
|
|
10153
10427
|
});
|
|
10154
10428
|
}, [adapter]);
|
|
10155
|
-
(0,
|
|
10429
|
+
(0, import_react38.useEffect)(() => {
|
|
10156
10430
|
if (onMessageReceived && chat.messages.length > 0) {
|
|
10157
10431
|
const lastMessage = chat.messages[chat.messages.length - 1];
|
|
10158
10432
|
if (lastMessage.role === "assistant" && !lastMessage.isStreaming) {
|
|
@@ -10160,12 +10434,12 @@ var CompactChat = (0, import_react37.memo)(function CompactChat2({
|
|
|
10160
10434
|
}
|
|
10161
10435
|
}
|
|
10162
10436
|
}, [chat.messages, onMessageReceived]);
|
|
10163
|
-
(0,
|
|
10437
|
+
(0, import_react38.useEffect)(() => {
|
|
10164
10438
|
if (onLoadingChange) {
|
|
10165
10439
|
onLoadingChange(chat.isLoading);
|
|
10166
10440
|
}
|
|
10167
10441
|
}, [chat.isLoading, onLoadingChange]);
|
|
10168
|
-
(0,
|
|
10442
|
+
(0, import_react38.useEffect)(() => {
|
|
10169
10443
|
if (onStateChange) {
|
|
10170
10444
|
onStateChange({
|
|
10171
10445
|
messages: chat.messages,
|
|
@@ -10173,24 +10447,24 @@ var CompactChat = (0, import_react37.memo)(function CompactChat2({
|
|
|
10173
10447
|
});
|
|
10174
10448
|
}
|
|
10175
10449
|
}, [chat.messages, chat.conversationId, onStateChange]);
|
|
10176
|
-
(0,
|
|
10450
|
+
(0, import_react38.useEffect)(() => {
|
|
10177
10451
|
if (connection.isConnected) {
|
|
10178
10452
|
resourcePicker.refreshProviders();
|
|
10179
10453
|
}
|
|
10180
10454
|
}, [connection.isConnected]);
|
|
10181
|
-
(0,
|
|
10455
|
+
(0, import_react38.useEffect)(() => {
|
|
10182
10456
|
if (showHistory && connection.isConnected) {
|
|
10183
10457
|
conversations.loadConversations();
|
|
10184
10458
|
}
|
|
10185
10459
|
}, [showHistory, connection.isConnected]);
|
|
10186
|
-
const handleSelectConversation = (0,
|
|
10460
|
+
const handleSelectConversation = (0, import_react38.useCallback)(
|
|
10187
10461
|
async (id) => {
|
|
10188
10462
|
setShowHistory(false);
|
|
10189
10463
|
await chat.loadConversation(id);
|
|
10190
10464
|
},
|
|
10191
10465
|
[chat]
|
|
10192
10466
|
);
|
|
10193
|
-
const handleDeleteConversation = (0,
|
|
10467
|
+
const handleDeleteConversation = (0, import_react38.useCallback)(
|
|
10194
10468
|
async (id) => {
|
|
10195
10469
|
await conversations.deleteConversation(id);
|
|
10196
10470
|
if (id === chat.conversationId) {
|
|
@@ -10199,14 +10473,14 @@ var CompactChat = (0, import_react37.memo)(function CompactChat2({
|
|
|
10199
10473
|
},
|
|
10200
10474
|
[conversations, chat]
|
|
10201
10475
|
);
|
|
10202
|
-
const handleNewChat = (0,
|
|
10476
|
+
const handleNewChat = (0, import_react38.useCallback)(() => {
|
|
10203
10477
|
chat.newConversation();
|
|
10204
10478
|
setShowHistory(false);
|
|
10205
10479
|
setTimeout(() => {
|
|
10206
10480
|
chatInputRef.current?.focus();
|
|
10207
10481
|
}, 0);
|
|
10208
10482
|
}, [chat]);
|
|
10209
|
-
(0,
|
|
10483
|
+
(0, import_react38.useEffect)(() => {
|
|
10210
10484
|
const handleKeyDown = (e) => {
|
|
10211
10485
|
const isMac2 = navigator.platform.includes("Mac");
|
|
10212
10486
|
const modifierKey = isMac2 ? e.metaKey : e.ctrlKey;
|
|
@@ -10220,20 +10494,19 @@ var CompactChat = (0, import_react37.memo)(function CompactChat2({
|
|
|
10220
10494
|
}, [handleNewChat]);
|
|
10221
10495
|
const isMac = typeof navigator !== "undefined" && navigator.platform.includes("Mac");
|
|
10222
10496
|
const shortcutKey = isMac ? "\u2318N" : "Ctrl+N";
|
|
10223
|
-
const defaultRenderMessage = (0,
|
|
10497
|
+
const defaultRenderMessage = (0, import_react38.useCallback)((message) => {
|
|
10224
10498
|
if (message.role === "tool") return null;
|
|
10225
10499
|
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));
|
|
10500
|
+
const {
|
|
10501
|
+
displayBlocks,
|
|
10502
|
+
isEffectivelyComplete,
|
|
10503
|
+
showIntermediateSteps,
|
|
10504
|
+
showStreamingTimeline,
|
|
10505
|
+
showThinkingSection
|
|
10506
|
+
} = getAssistantDisplayState(message);
|
|
10507
|
+
const isToolCallsStreaming = message.isToolCallsStreaming ?? ((message.toolCalls?.some((tc) => tc.status === "running") ?? false) || (displayBlocks?.some((b) => b.type === "tool_call" && b.toolStatus === "running") ?? false));
|
|
10235
10508
|
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 &&
|
|
10509
|
+
!isUser && showIntermediateSteps && displayBlocks && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(IntermediateSteps, { blocks: displayBlocks, strings: mergedStrings }),
|
|
10237
10510
|
showThinkingSection && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
10238
10511
|
ThinkingSection,
|
|
10239
10512
|
{
|
|
@@ -10241,18 +10514,18 @@ var CompactChat = (0, import_react37.memo)(function CompactChat2({
|
|
|
10241
10514
|
currentThinking: message.currentThinking,
|
|
10242
10515
|
isStreaming: message.isThinkingStreaming,
|
|
10243
10516
|
isPaused: message.isThinkingPaused,
|
|
10244
|
-
isComplete:
|
|
10517
|
+
isComplete: isEffectivelyComplete,
|
|
10245
10518
|
strings: mergedStrings
|
|
10246
10519
|
}
|
|
10247
10520
|
),
|
|
10248
|
-
showStreamingTimeline &&
|
|
10521
|
+
showStreamingTimeline && displayBlocks && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
10249
10522
|
StreamingTimeline,
|
|
10250
10523
|
{
|
|
10251
|
-
blocks:
|
|
10524
|
+
blocks: displayBlocks,
|
|
10252
10525
|
currentThinking: message.currentThinking,
|
|
10253
10526
|
isThinkingStreaming: message.isThinkingStreaming,
|
|
10254
10527
|
isToolCallsStreaming,
|
|
10255
|
-
isComplete:
|
|
10528
|
+
isComplete: isEffectivelyComplete,
|
|
10256
10529
|
strings: mergedStrings
|
|
10257
10530
|
}
|
|
10258
10531
|
),
|
|
@@ -10274,11 +10547,11 @@ var CompactChat = (0, import_react37.memo)(function CompactChat2({
|
|
|
10274
10547
|
] }) });
|
|
10275
10548
|
}, [mergedStrings, linkHandler]);
|
|
10276
10549
|
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,
|
|
10550
|
+
const baseColors = (0, import_react38.useMemo)(() => {
|
|
10278
10551
|
if (!floating) return null;
|
|
10279
10552
|
return getBaseColors(resolvedIsDarkMode);
|
|
10280
10553
|
}, [floating, resolvedIsDarkMode]);
|
|
10281
|
-
const containerStyle = (0,
|
|
10554
|
+
const containerStyle = (0, import_react38.useMemo)(() => {
|
|
10282
10555
|
const baseStyle = floating && baseColors ? {
|
|
10283
10556
|
...accentStyle,
|
|
10284
10557
|
// Override CSS variables with tinted colors for consistency with app
|
|
@@ -10306,7 +10579,7 @@ var CompactChat = (0, import_react37.memo)(function CompactChat2({
|
|
|
10306
10579
|
"data-chat-font-size": resolvedConfig?.fontSize || "normal",
|
|
10307
10580
|
children: [
|
|
10308
10581
|
/* @__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 ? (
|
|
10582
|
+
!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
10583
|
// Embedded mode: left-aligned buttons (collapse, float, history, new chat)
|
|
10311
10584
|
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center gap-0.5", style: { WebkitAppRegion: "no-drag" }, children: [
|
|
10312
10585
|
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "chat-tooltip-wrapper", children: [
|
|
@@ -10481,6 +10754,7 @@ var CompactChat = (0, import_react37.memo)(function CompactChat2({
|
|
|
10481
10754
|
(() => {
|
|
10482
10755
|
if (hideInput && !shouldRenderInputExternally) return null;
|
|
10483
10756
|
const disableInput = !!chat.pendingInterrupt || chat.isLoading && !chat.isStreaming;
|
|
10757
|
+
const allowEmptySubmit = resourcePicker.attachedResources.length > 0 || chat.sessionResources.length > 0;
|
|
10484
10758
|
const addResourceButtonSlot = resourceProviders.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
10485
10759
|
AddResourceButton,
|
|
10486
10760
|
{
|
|
@@ -10514,6 +10788,7 @@ var CompactChat = (0, import_react37.memo)(function CompactChat2({
|
|
|
10514
10788
|
disabled: disableInput,
|
|
10515
10789
|
isStreaming: chat.isStreaming,
|
|
10516
10790
|
isLoading: chat.isLoading,
|
|
10791
|
+
allowEmptySubmit,
|
|
10517
10792
|
autoFocus: true,
|
|
10518
10793
|
leftSlot: addResourceButtonSlot
|
|
10519
10794
|
}
|
|
@@ -10662,5 +10937,6 @@ var CompactChat = (0, import_react37.memo)(function CompactChat2({
|
|
|
10662
10937
|
useResourcePicker,
|
|
10663
10938
|
useStandaloneI18n,
|
|
10664
10939
|
useStandaloneTheme,
|
|
10665
|
-
useTheme
|
|
10940
|
+
useTheme,
|
|
10941
|
+
useWindowDragLock
|
|
10666
10942
|
});
|