@yushaw/sanqian-chat 0.2.20 → 0.2.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -141,10 +141,12 @@ function useChat(options) {
141
141
  case "start": {
142
142
  currentRunIdRef.current = event.run_id;
143
143
  if (pendingCancelRef.current) {
144
- const pendingCancel = pendingCancelFnRef.current;
145
- clearPendingCancel();
146
- pendingCancel?.();
147
- cancelRef.current = null;
144
+ const pendingCancel = pendingCancelFnRef.current || cancelRef.current;
145
+ if (pendingCancel) {
146
+ clearPendingCancel();
147
+ pendingCancel();
148
+ cancelRef.current = null;
149
+ }
148
150
  }
149
151
  break;
150
152
  }
@@ -561,8 +563,11 @@ function useChat(options) {
561
563
  }
562
564
  }
563
565
  }, [clearPendingCancel, flushTypewriter, onConversationChange, onError, resetStreamBuffers]);
564
- const sendMessage = useCallback(async (content, sendOptions) => {
565
- if (!content.trim()) return;
566
+ const trySendMessage = useCallback(async (content, sendOptions) => {
567
+ const trimmedContent = content.trim();
568
+ const hasAttachedResources = (sendOptions?.attachedResources?.length ?? 0) > 0;
569
+ const hasSessionResources = sessionResources.length > 0;
570
+ if (!trimmedContent && !hasAttachedResources && !hasSessionResources) return false;
566
571
  setError(null);
567
572
  clearPendingCancel();
568
573
  suppressStreamRef.current = false;
@@ -575,7 +580,7 @@ function useChat(options) {
575
580
  const userMessage = {
576
581
  id: crypto.randomUUID(),
577
582
  role: "user",
578
- content: content.trim(),
583
+ content: trimmedContent,
579
584
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
580
585
  attachedResources: sendOptions?.attachedResources?.length ? sendOptions.attachedResources : void 0
581
586
  };
@@ -589,14 +594,16 @@ function useChat(options) {
589
594
  blocks: [],
590
595
  isComplete: false
591
596
  };
592
- setMessages((prev) => [...prev, userMessage, assistantMessage]);
597
+ const shouldRenderUserMessage = trimmedContent.length > 0 || hasAttachedResources;
598
+ setMessages(
599
+ (prev) => shouldRenderUserMessage ? [...prev, userMessage, assistantMessage] : [...prev, assistantMessage]
600
+ );
593
601
  setIsLoading(true);
594
602
  setIsStreaming(true);
595
603
  const sessionResourceIds = sessionResources.map((r) => r.fullId);
596
604
  const savedSessionResources = sessionResourceIds.length > 0 ? [...sessionResources] : null;
597
605
  try {
598
606
  if (!adapter.isConnected()) await adapter.connect();
599
- const trimmedContent = content.trim();
600
607
  const shouldSendHistory = !conversationIdRef.current;
601
608
  const historyMessages = shouldSendHistory ? messagesRef.current.filter((m) => m.role === "user" || m.role === "assistant").map((m) => ({ role: m.role, content: m.content })) : [];
602
609
  const apiMessages = [...historyMessages, { role: "user", content: trimmedContent }];
@@ -617,6 +624,12 @@ function useChat(options) {
617
624
  }
618
625
  );
619
626
  cancelRef.current = cancel;
627
+ if (pendingCancelRef.current) {
628
+ clearPendingCancel();
629
+ cancel();
630
+ cancelRef.current = null;
631
+ }
632
+ return true;
620
633
  } catch (err) {
621
634
  const errorMessage = err instanceof Error ? err.message : "Failed to send message";
622
635
  setError(errorMessage);
@@ -633,8 +646,12 @@ function useChat(options) {
633
646
  }
634
647
  setIsLoading(false);
635
648
  setIsStreaming(false);
649
+ return false;
636
650
  }
637
651
  }, [adapter, clearPendingCancel, handleStreamEvent, onError, resetStreamBuffers, sessionResources]);
652
+ const sendMessage = useCallback(async (content, sendOptions) => {
653
+ await trySendMessage(content, sendOptions);
654
+ }, [trySendMessage]);
638
655
  const stopStreaming = useCallback(() => {
639
656
  const shouldDelayCancel = !currentRunIdRef.current;
640
657
  if (shouldDelayCancel) {
@@ -773,6 +790,7 @@ function useChat(options) {
773
790
  conversationTitle,
774
791
  pendingInterrupt,
775
792
  sendMessage,
793
+ trySendMessage,
776
794
  stopStreaming,
777
795
  clearMessages,
778
796
  setError,
@@ -1311,6 +1329,35 @@ var CSS_VARIABLES = `/**
1311
1329
  user-select: text;
1312
1330
  }
1313
1331
 
1332
+ /* ========================================
1333
+ Draggable Regions (Electron)
1334
+ ======================================== */
1335
+ .chat-drag-region {
1336
+ -webkit-app-region: drag;
1337
+ }
1338
+
1339
+ /*
1340
+ * Interactive descendants inside drag regions must explicitly opt out of drag,
1341
+ * otherwise icon-only click targets can become non-clickable in Electron.
1342
+ */
1343
+ .chat-drag-region button,
1344
+ .chat-drag-region button *,
1345
+ .chat-drag-region a,
1346
+ .chat-drag-region a *,
1347
+ .chat-drag-region input,
1348
+ .chat-drag-region textarea,
1349
+ .chat-drag-region select,
1350
+ .chat-drag-region [role="button"],
1351
+ .chat-drag-region [role="button"] * {
1352
+ -webkit-app-region: no-drag;
1353
+ }
1354
+
1355
+ /* Modal overlays should get click priority over drag regions. */
1356
+ :root[data-window-drag-locked="true"] .chat-drag-region {
1357
+ -webkit-app-region: no-drag !important;
1358
+ pointer-events: none !important;
1359
+ }
1360
+
1314
1361
  /* ========================================
1315
1362
  Font Size Scaling
1316
1363
  Applies zoom to scale entire chat UI including rem units.
@@ -1506,6 +1553,16 @@ code {
1506
1553
  animation: chat-cursor-breathing 1s ease-in-out infinite;
1507
1554
  }
1508
1555
 
1556
+ /* Streaming cursor - version-agnostic fallback (works across streamdown 1.x/2.x) */
1557
+ .chat-streaming-cursor {
1558
+ --streamdown-caret: '\u258C';
1559
+ }
1560
+ .chat-streaming-cursor > *:last-child::after {
1561
+ content: var(--streamdown-caret, '\u258C');
1562
+ color: var(--chat-accent) !important;
1563
+ animation: chat-cursor-breathing 1s ease-in-out infinite !important;
1564
+ }
1565
+
1509
1566
  @keyframes chat-fade-in {
1510
1567
  from {
1511
1568
  opacity: 0;
@@ -5045,6 +5102,8 @@ function useFocusPersistence({
5045
5102
  const container = containerRef.current;
5046
5103
  if (!container) return;
5047
5104
  const handleClick = (e) => {
5105
+ if (e.button !== 0 || e.ctrlKey) return;
5106
+ if (!(e.target instanceof Element)) return;
5048
5107
  const target = e.target;
5049
5108
  if (!container.contains(target)) return;
5050
5109
  if (target.closest('button, a, input, textarea, [contenteditable], [role="menu"], [role="dialog"], [role="listbox"]')) {
@@ -5399,6 +5458,50 @@ function useResourcePicker(options) {
5399
5458
  };
5400
5459
  }
5401
5460
 
5461
+ // src/renderer/hooks/useWindowDragLock.ts
5462
+ import { useEffect as useEffect11 } from "react";
5463
+ var DRAG_LOCK_ATTR = "data-window-drag-locked";
5464
+ var DRAG_LOCK_STATE_KEY = "__sanqian_window_drag_lock_state__";
5465
+ function hasDocument() {
5466
+ return typeof document !== "undefined";
5467
+ }
5468
+ function getWindowDragLockState() {
5469
+ const globalRef = globalThis;
5470
+ if (!globalRef[DRAG_LOCK_STATE_KEY]) {
5471
+ globalRef[DRAG_LOCK_STATE_KEY] = { count: 0 };
5472
+ }
5473
+ return globalRef[DRAG_LOCK_STATE_KEY];
5474
+ }
5475
+ function applyDragLockState() {
5476
+ if (!hasDocument()) return;
5477
+ const root = document.documentElement;
5478
+ if (getWindowDragLockState().count > 0) {
5479
+ root.setAttribute(DRAG_LOCK_ATTR, "true");
5480
+ } else {
5481
+ root.removeAttribute(DRAG_LOCK_ATTR);
5482
+ }
5483
+ }
5484
+ function acquireWindowDragLock() {
5485
+ if (!hasDocument()) return () => {
5486
+ };
5487
+ const state = getWindowDragLockState();
5488
+ state.count += 1;
5489
+ applyDragLockState();
5490
+ let released = false;
5491
+ return () => {
5492
+ if (released) return;
5493
+ released = true;
5494
+ state.count = Math.max(0, state.count - 1);
5495
+ applyDragLockState();
5496
+ };
5497
+ }
5498
+ function useWindowDragLock(active) {
5499
+ useEffect11(() => {
5500
+ if (!active) return;
5501
+ return acquireWindowDragLock();
5502
+ }, [active]);
5503
+ }
5504
+
5402
5505
  // src/core/history.ts
5403
5506
  function safeParseArgs(value) {
5404
5507
  if (!value) return void 0;
@@ -5447,6 +5550,50 @@ function getNumericMessageId(message) {
5447
5550
  }
5448
5551
  return void 0;
5449
5552
  }
5553
+ function parseAttachedResourceRef(rawRef) {
5554
+ const segments = rawRef.split(":");
5555
+ if (segments.length < 2) return null;
5556
+ const providerId = segments.slice(0, -1).join(":").trim();
5557
+ const resourceId = segments[segments.length - 1].trim();
5558
+ if (!providerId || !resourceId) return null;
5559
+ return { providerId, resourceId };
5560
+ }
5561
+ function normalizeAttachedResources(raw) {
5562
+ if (!Array.isArray(raw)) return void 0;
5563
+ const resources = [];
5564
+ const seen = /* @__PURE__ */ new Set();
5565
+ for (const item of raw) {
5566
+ let providerId = "";
5567
+ let resourceId = "";
5568
+ let entry = null;
5569
+ if (typeof item === "string") {
5570
+ const parsed = parseAttachedResourceRef(item.trim());
5571
+ if (parsed) {
5572
+ providerId = parsed.providerId;
5573
+ resourceId = parsed.resourceId;
5574
+ }
5575
+ } else if (item && typeof item === "object") {
5576
+ entry = item;
5577
+ const providerRaw = typeof entry.providerId === "string" ? entry.providerId : typeof entry.provider_id === "string" ? entry.provider_id : "";
5578
+ const resourceRaw = typeof entry.resourceId === "string" ? entry.resourceId : typeof entry.resource_id === "string" ? entry.resource_id : "";
5579
+ providerId = providerRaw.trim();
5580
+ resourceId = resourceRaw.trim();
5581
+ }
5582
+ if (!providerId || !resourceId) continue;
5583
+ const dedupeKey = `${providerId}\0${resourceId}`;
5584
+ if (seen.has(dedupeKey)) continue;
5585
+ seen.add(dedupeKey);
5586
+ resources.push({
5587
+ providerId,
5588
+ resourceId,
5589
+ title: entry && typeof entry.title === "string" && entry.title.trim().length > 0 ? entry.title.trim() : resourceId,
5590
+ summary: entry && typeof entry.summary === "string" && entry.summary.trim().length > 0 ? entry.summary.trim() : void 0,
5591
+ type: entry && typeof entry.type === "string" && entry.type.trim().length > 0 ? entry.type.trim() : void 0,
5592
+ icon: entry && typeof entry.icon === "string" && entry.icon.trim().length > 0 ? entry.icon.trim() : void 0
5593
+ });
5594
+ }
5595
+ return resources.length > 0 ? resources : void 0;
5596
+ }
5450
5597
  function mergeConsecutiveAssistantMessages(rawMessages) {
5451
5598
  const result = [];
5452
5599
  let i = 0;
@@ -5616,7 +5763,8 @@ function mergeConsecutiveAssistantMessages(rawMessages) {
5616
5763
  timestamp: msg.timestamp || msg.created_at || (/* @__PURE__ */ new Date()).toISOString(),
5617
5764
  toolCalls: parseToolCalls(msg.toolCalls || msg.tool_calls),
5618
5765
  thinking: msg.thinking || void 0,
5619
- filePaths: msg.filePaths
5766
+ filePaths: msg.filePaths,
5767
+ attachedResources: normalizeAttachedResources(msg.attachedResources || msg.attached_resources)
5620
5768
  });
5621
5769
  i++;
5622
5770
  }
@@ -6300,7 +6448,7 @@ function createSdkAdapter(config) {
6300
6448
  import { SanqianSDK } from "@yushaw/sanqian-sdk/browser";
6301
6449
 
6302
6450
  // src/renderer/components/MessageList.tsx
6303
- import { memo, useRef as useRef5, useEffect as useEffect11, useCallback as useCallback9 } from "react";
6451
+ import { memo, useRef as useRef5, useEffect as useEffect12, useCallback as useCallback9 } from "react";
6304
6452
  import { jsx as jsx3 } from "react/jsx-runtime";
6305
6453
  var SCROLL_THRESHOLD = 100;
6306
6454
  var MessageList = memo(function MessageList2({
@@ -6326,12 +6474,12 @@ var MessageList = memo(function MessageList2({
6326
6474
  },
6327
6475
  [scrollBehavior]
6328
6476
  );
6329
- useEffect11(() => {
6477
+ useEffect12(() => {
6330
6478
  if (autoScroll && isNearBottomRef.current) {
6331
6479
  scrollToBottom();
6332
6480
  }
6333
6481
  }, [messages, autoScroll, scrollToBottom]);
6334
- useEffect11(() => {
6482
+ useEffect12(() => {
6335
6483
  scrollToBottom("instant");
6336
6484
  isNearBottomRef.current = true;
6337
6485
  }, [scrollToBottom]);
@@ -6359,19 +6507,16 @@ var MessageBubble = memo2(function MessageBubble2({
6359
6507
  }) {
6360
6508
  const isStreaming = message.isStreaming ?? false;
6361
6509
  return /* @__PURE__ */ jsxs("div", { className, "data-role": message.role, "data-streaming": isStreaming, children: [
6362
- /* @__PURE__ */ jsx4("div", { className: "message-content", children: renderContent ? renderContent(message.content, isStreaming) : /* @__PURE__ */ jsxs(Fragment, { children: [
6363
- message.content,
6364
- isStreaming && /* @__PURE__ */ jsx4("span", { className: "streaming-cursor", children: "\u258C" })
6365
- ] }) }),
6510
+ /* @__PURE__ */ jsx4("div", { className: "message-content", children: renderContent ? renderContent(message.content, isStreaming) : /* @__PURE__ */ jsx4(Fragment, { children: message.content }) }),
6366
6511
  children
6367
6512
  ] });
6368
6513
  });
6369
6514
 
6370
6515
  // src/renderer/components/SanqianChat.tsx
6371
- import { memo as memo13, useCallback as useCallback17, useEffect as useEffect20, useMemo as useMemo8, useRef as useRef13 } from "react";
6516
+ import { memo as memo13, useCallback as useCallback17, useEffect as useEffect21, useMemo as useMemo8, useRef as useRef13 } from "react";
6372
6517
 
6373
6518
  // src/renderer/utils/chatConfig.ts
6374
- import { useEffect as useEffect12, useMemo as useMemo3, useState as useState10 } from "react";
6519
+ import { useEffect as useEffect13, useMemo as useMemo3, useState as useState10 } from "react";
6375
6520
  var getSystemTheme = () => {
6376
6521
  if (typeof window === "undefined") return "light";
6377
6522
  return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
@@ -6381,7 +6526,7 @@ function useResolvedTheme(mode = "auto") {
6381
6526
  if (mode === "auto") return getSystemTheme();
6382
6527
  return mode === "dark" ? "dark" : "light";
6383
6528
  });
6384
- useEffect12(() => {
6529
+ useEffect13(() => {
6385
6530
  if (mode !== "auto") {
6386
6531
  setResolvedTheme(mode === "dark" ? "dark" : "light");
6387
6532
  return;
@@ -6485,7 +6630,7 @@ function resolveOnPin(onPin) {
6485
6630
  }
6486
6631
 
6487
6632
  // src/renderer/utils/useChatHeader.tsx
6488
- import { useCallback as useCallback10, useEffect as useEffect13, useMemo as useMemo4, useRef as useRef6, useState as useState11 } from "react";
6633
+ import { useCallback as useCallback10, useEffect as useEffect14, useMemo as useMemo4, useRef as useRef6, useState as useState11 } from "react";
6489
6634
 
6490
6635
  // src/renderer/assets/sanqianLogo.ts
6491
6636
  var SANQIAN_LOGO_DATA_URI = "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyBpZD0iTGF5ZXJfMiIgZGF0YS1uYW1lPSJMYXllciAyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0MTUuODcgNDI4LjIiPgogIDxnIGlkPSJMYXllcl8xLTIiIGRhdGEtbmFtZT0iTGF5ZXIgMSI+CiAgICA8ZyBpZD0iQzhvaUxXIj4KICAgICAgPGc+CiAgICAgICAgPHBhdGggZD0iTTQwNC45LDE1OC4wM2wxLjk4LTEuMDFjLS4zMSw2LjM1LDEuMDQsMTIuNTYsMS43NCwxOC44Mi41Myw0LjcyLDEuNjIsOC41NywxLjI2LDE0LjY4LTEuMDcsMTguNDEtNy4wOCwzNS45Ni0xMS45OCw1My41bDcuOTUtMTYuNTRjMy43MS0xMi4wOCw2Ljc4LTI0LjI0LDguMDUtMzYuODdsMS45Ny0uMWMtMS43MSw0LjkxLTEuNDQsMTAuNjYtMi4yNiwxNS43NC00LjY3LDI5LjA1LTE3LjgzLDU4LjI3LTM1LjMxLDgxLjY5LTguNzYsMTEuNzMtMTkuNzgsMjEuMzUtMjguNDQsMzIuNTYtMi45OSwzLjg4LTEyLjM4LDcuOTktMTYuMjMsMTAuNTUtMi4wOCwxLjM4LTQuOTQsNS44Ny02LjQ4LDcuMDEtNiw0LjQ1LTE3LjE5LDUuNDMtMjIuMjYsMTEuNDcsMS4xLDEuMTksMy42OS0uNTQsNC45NS0xLjA1LDE1LjQ0LTYuMiwyOC45NC0xMy45Niw0Mi42MS0yMy40LDQuNjMsMS4wNi0uODQsMi4zMS0xLjg5LDMuMDgtNDEuOTYsMzAuNTUtOTAuNDYsNDYuMy0xNDEuOTQsMjcuNjQtMTkuMzEtNy0yNi4yMS0xOC45Ny00MC41NS0yNi40NS0xMy4xLTYuODMtMTUuOTktMTEuNTctMjUuMTgtMjIuNTQtMi45My0zLjUtMTAuNzEtMTEuNDctMTIuNDItMTQuODYtLjU2LTEuMTEtNi4yLTIwLjQ4LTYuMjEtMjEuNi0uMDQtNC4zNSwzLjE0LTkuOTcsMy42My0xNC44NC44LTcuOTMtMi45Ny0xOC45MSwzLTI0LjQ5LjY3LDMuMTQuNzgsNi41NSwxLjkxLDkuNjEuNTEsMS4zNy0uMzYsMS43LDIuMDksMS40LDEuOTQtNC4yNi0uMzYtOS45OS4xNy0xMy4yNSwxLjIxLTcuNDcsOC4zLTIxLjg0LDEzLjMzLTI3Ljc2LDUuMzUtNi4yOSwxNC4xMy0xNC4wOSwyMi41MS0xNC40OWwtMTAsOS40OSw2Ljk5LTEuNWMtMy4wNCw0LjgxLTcuNDUsOC43My0xMC40MSwxMy41OS01LjA2LDguMjktNS44NiwxNy44MS02LjU5LDI3LjQzbDQuMDIsMTkuNDljMi4wOC0uOTQuNTUtNS4wNSwxLjItNy4yOS4yNC0uODMsMi4yNi0zLjA5LDIuNzgtMi43LDMuMiwxNC4wNiwxMC40NSwyNC41NSwyMC40MiwzNC42MSwyNS4xLDI1LjM1LDY0LjA0LDMyLjc4LDk3LjI3LDE5LjU2LDguMDMtMy4xOSwxNS43LTguOTYsMjMuMzItMTIuMTdsLTIsMi45OGgxLjQ5YzE3LjE1LTEyLjY2LDMzLjYzLTI3LjExLDQyLjUzLTQ2Ljk5bDIsLjUxLS4wMyw1LjQ4LDguMy0xNi4yLDkuNy0yNy43OWMuNDUsNy41OS0yLjYxLDE0LjY3LTQuNDQsMjEuODYtLjkyLDMuNjItLjQ1LDUuNzgtMi4zOSwxMC44LTYuNTksMTcuMDgtMTkuMTgsMzMuMzEtMzIuMTYsNDUuODVsMy45OC0uNTFjLS4wMy40Ny4xNywxLjA1LDAsMS40OS0xLjg3LDQuNzItMjQuMzMsMjAuMTQtMjkuNzEsMjMuMy0xMC4zMSw2LjA1LTIxLjY3LDExLjEtMzMuMjcsMTQuMjMtLjE2LDEuODUsMy4yNi45OCw0LjM3Ljg2LDM2LjgtNC4wMiw3NS4yOC0yOS43NCw5NS40NS02MC41NSwxMS40MS0xNy40MywxNi42Ni0zMy4yNCwyMS44Ny01My4xMy44OC0zLjM2LDMuMzUtNi4wOSwyLjMyLTEwLjE5LDEuNjctLjI2LDEuMDcsMi40MSwxLjA0LDMuNTMtLjA5LDIuODUtLjkyLDUuMjMtMS4wOSw3LjkzLS4wNywxLjA4LS42NCwzLjc5LDEuMDMsMy41Mmw0Ljk2LTE5LjU0YzEuNTYtMTcuMzEsMy41NC0zMi4yOS43NS00OS42Ni0xLjAxLTYuMy00LjA2LTEzLjMyLTQuNzItMTkuMy0uMjQtMi4xNy40LTIuNjQsMS4yNS0uMjQuNzcsMi4xNywxLjE5LDQuNTIsMS43Nyw2Ljc1LDEuNzEuMjcsMS4wNy0yLjQuOTEtMy40LS42LTMuNTctMy4xLTEwLjk4LTQuNDQtMTQuNTctMy43OS0xMC4yMS0xMC4zMS0xOS42My0xMy40Ny0zMC4wMSwxLjU0Ljk1LDMuMTksMy43MSw0LjE5LDUuMywxMy4xMywyMC45OCwyMC42OSw0NC4zMiwyNC44Miw2OC43WiIvPgogICAgICAgIDxnPgogICAgICAgICAgPHBhdGggZD0iTTIyMC44OSw0MDYuMDJjLS4yNiwxLjMzLDEuODMsMS42LDIuNzQsMS43NSwzMi4xLDUuMjksNTguMjgsMS41MSw4OC4yNC0xMS4yNmwyOS4wMS0xNS40OGMtNC43Nyw1LjEyLTEyLjEyLDkuNjQtMTguMzMsMTMuMTYtNy4wNCwzLjk5LTE5LjI3LDcuNzItMjQuNjgsMTEuMzItLjQxLjI3LTEuMzIsMS4yNC0uOTksMS41aDUuOTljLTYuNjcsMS40Ny0xMy40OCw0LjgzLTE5Ljk3LDYuNTQtNS4xMywxLjM1LTE3LjY2LDIuMzctMjEuMDQsMy45Ni0uNDYuMjEtMS4yNiwxLjMtLjk4LDEuNTFsNC45OSwxYy0yOC4zLDUuNTktNTcuMTQtLjQ4LTg0LjQ4LTguMDEtMS42LDEuMDUuNzUsMS4xOCwxLjQ1LDEuNTMsMTMuMzMsNi42OSwyOS4yMiwxMC4wNyw0NC4wNCwxMS40OWwtMS4wMSwxLjk4LDUsLjAyYy4yNSwxLjcyLTIuMzcsMS4wNi0zLjQ4Ljk4LTMxLjc4LTIuNDEtNjcuMzktMTYuNTMtOTMuNDMtMzQuNTgtMTcuNDYtMTIuMS0zMS4xNS0yNy4wMy00NS41NC00MS40NWwtMjAuNTMtMzEuOTYtMSwzLjk5Yy0uMTItLjcxLTEuOTktOS4yNC00LjAxLTYuOTguNjksMi43NSwyLjYzLDUuNDQsMy41NCw3Ljk1LjM0Ljk0LDEuMzIsMy4yNS0uNTMsMy4wMy0xMC42OC0yMS44NS0xNy44My00NS45NS0xOS4wNS03MC40NS0uNDItOC40OSwzLjMtNDEuNCw4LjE2LTQ3LjQyLjE3LS4yMSwzLjA2LDEuMTgsMy44Ny0yLjY1bC0xLjk4LS40N2MtLjg1LTUuMDQsMy42NC02LjUyLDUuNjYtOS44MnM5LjM3LTE2LjcsMTAuMzEtMTkuNzFjLjE2LS41MS4yNy0xLjYzLS40OC0xLjQ4LTIuNzUsMi4xOC0zLjgzLDUuNTktNS42Niw4LjM0LS42OCwxLjAyLTIuMDIsMy4xMi0xLjgzLjE4LDExLjc1LTI0LjQ3LDI4LjEzLTQyLjQxLDUwLjY1LTU3LjM1LDUuOTYtMy45NSwxMi44Mi02LjUsMTguMzMtMTEuMTYtOS43My41LTIyLjE4LDQuMzItMzAuOTksOC41LTMuMywxLjU3LTguNTIsNi4wOC0xMS4wNyw2Ljk2LTEuNjQuNTctMy4wOC0uNi01LjIxLjUtMS44LjkzLTEwLjY0LDguNi0xMi43NCwxMC41MS0yNC43OSwyMi41Ni00MS4yNiw1Ny41MS00Niw5MC41MS0xLjYxLjA1LTIuMDUtMy41My0yLjA0LTQuNTMuMDUtNC4wOSwxLjMtMTAuMjksMi4wNS0xNC40NmwtMy44OS4xYy0yLjIsMTEuOTYtNS43OSwyMy41OC01LjEyLDM1Ljg4bC0yLTYuOTljLTEuNDctLjA5LTEuNzYsMy41OS0xLjg3LDQuNjEtMi40NywyMy44NSw2LjI4LDU4LjIxLDE1LjQsODAuMzYsMS4wMiwyLjQ5LDkuMTQsMTcuMjEsOC40OCwxOC4wMS0xLjU5LDEuOTItMi4xNC0xLjQ5LTIuNDctMS45OS0xMy4zNC0yMC4yMi0yMS42Mi00My4xLTI1LjU0LTY3LjAxbC0xLjk4LDEuMDFjLTIuMzYtMTUuMTEtNC45NS0yOS4wNy00LjA1LTQ0LjU0LjMyLTUuNDQsMi42Mi0xMC44NywyLjAzLTE2LjQ2bC0zLjk4LDE2LjUxYy0uOTUsMTAuMzEtLjU5LDIwLjY4LTEuMDEsMzEtLjA1LDEuMjEuNzYsMy43Mi0uOTksMy40OC0yLjAxLTE4LjI0LS41NC0zNi4zMSwzLjI4LTU0LjIsNS42OS0yNi42LDE4LjI4LTU0LjI3LDM2LjE5LTc0LjgxLDEyLjUzLTE0LjM3LDI4LjEyLTI3Ljk5LDQyLjg4LTM4LjY4LDIuMDktMS41MSw1LjA0LTMuOCw3LjMxLTUuMTMsOC4xLTQuNzIsMTcuODQtNS45OSwyNS4zMS0xMS42OC0uNTgtMS4xMS0zLjA2LS4zNi00LjA2LS4wNi00LjkzLDEuNDUtMTIuMTUsNC4wNy0xNi45Miw2LjA4LTUuOTIsMi41LTExLjU0LDUuNzEtMTcsOS4wNmwtMy4wMS0xLjU2YzcuMzEtMy4yNywxMy41My03LjI4LDIxLjAzLTEwLjQ4LDQxLjYzLTE3LjcyLDEwNS4zMi0yMCwxMzcuMzYsMTYuNTMsNy40NSw4LjQ5LDE5LjI1LDIyLjU4LDI1LjA1LDMwLjk5LDEuODgsMi43MiwyLjc5LDUuNzQsMS41NSw4Ljk0aDMuMDJjLS41OC45NC0uOTksNi41Ni0uOCw2Ljg0LjQ0LjY1LDIuOTcuNjQsMy4zOCwyLjY0LjI5LDEuNDMsMS40OSwxNC43LDEuNDMsMTUuOTUtLjAzLjYtMS44MS40Ny0yLjAxLDEuMjUtLjg0LDMuMjcuNDcsMTIuNTEtLjA3LDE2LjY4LS45NSw3LjM0LTYuMTksMTAuMTItOS44MywxNS4yNy0xLjI4LDEuODEtMS45OCw2LjU3LTQuMTUsNy44NC0xLjc3LDEuMDQtNC45NS42NC03LjE4LDEuNjEtMi4zNCwxLjAyLTMuNTEsNi42Ni03Ljc4LDQuOTNsMi45OS0xMWMtMy4zOSw0LjA2LTEzLjU2LDEwLjAzLTEwLjIxLjI4LDEuMzEtMy44MS44NC0zLjI4LDEuNTEtNi41NC44MS0zLjkyLDMuNzktMTIuOTIsMy43MS0xNi4xNi0uMDEtLjQyLTEuOTktLjk4LTIuNy0yLjM2LTQuMDItNy44Mi02LjM1LTE1LjE3LTEyLjY2LTIxLjg3LTExLjMtMTItNDIuMzMtMTguMi01Ny44OS0xNC4xLTE2Ljg4LDQuNDUtNDQuNjUsMjYuNDQtNTEuMyw0Mi43LTgsMTkuNTgtMTUuMTcsMzkuNjctMTIuMyw2MS4zOCw0LjA5LDMwLjg2LDE2LjE2LDUzLjYsMzMuNCw3OC42LDEuNTMsMi4yMiw0LjIxLDMuNTksNS40NCw2LjA1LTMuNzktMS4zNy03Ljc1LTUuOTQtMTAuNTEtOC45OC0xMC45My0xMS45OS0xOS44OS0yNi4yNS0yNi41LTQxLjAxLTMuMDMsMS40LDMuMjksNi43Mi0uOTcsNy45OWwtNy4wMy0xNy45OS0xLjk4LDEuOTljLS40Mi0yLjYtMS4wOC04LjIzLTQuMDItOC40OCw0LjMsMjguMjgsMTIuOTgsNTIuNjYsMzEuMDQsNzQuOTYsMjcuNDgsMzMuOTQsNzIuOTMsNjEuMzIsMTE3LjM1LDYyLjY1bDguNjIsMS44OGgtMjFaIi8+CiAgICAgICAgICA8cGF0aCBkPSJNMjg4LjQ4LDQxLjQzYzE3LDEzLjA0LDI2LjQ2LDI0LjkxLDM2LjU4LDQzLjkyLDE1Ljc5LDI5LjY4LDIyLjc5LDYyLjM3LDE1LjgyLDk1LjY3LTEuNjcuMjYtMS4wOS0yLjQzLTEuMDMtMy41My4yLTMuNDksMS42NC02Ljg3LDEuMDMtMTAuNDdsLTEuNTEuOThjLTIuOCwyMS43Mi0xMC41OSw0NS44NC0yMy4wNSw2My45NS01LjY4LDguMjYtOS44NSwxMC41NS0xNi45NSwxNi4wNS0yLjk1LDIuMjktNi4xOSw4LjE3LTkuNDgsNy41MiwxLjA3LTEuODMsNS44NS0zLjk1LDQuNDktNi41MWwtMTAuNDksNyw4Ljk5LTguNS0xLjQ4LS40OWMtMTguNjIsMTcuMTktNDguNjUsMjkuNDYtNzMuNTEsMTkuNDQtMS42LS42NS0yLjQ1LjEtMS45OS0yLjQ1LDEzLjc2LDYuMTcsMjcuODEsMi4wMyw0MC45Ny0zLjUyLDM2LjAyLTE1LjE5LDU3LjE2LTUzLjQ4LDU2LjkyLTkyLjA5LS4wMi0zLjE5LS41Mi0xMS43LTIuODktMTMuMzksMS44OSwxMC0uMywyMi40Ny0zLjMxLDMyLjIxLS4zMiwxLjA1LS4yNiwzLjAzLTEuNjksMi43OSw5Ljc1LTUxLjA4LTIwLjUyLTEwMC41NC02My43MS0xMjUuOC02LjQ1LTMuNzctMTQuMzUtNS42Ni0xOS41Ni0xMC40OWwtMTguNzQtNi43YzIuMDktLjA3LDQuMTgtLjE0LDYuMjYuMjMsMjAuOTcsMy43NywzOS44NCwxNC4zNiw1OC40NCwyMy41NSwxLjczLjg1LDMuNDUsMS44Myw1LjA0LDIuOSwyLjgyLDEuODgsOC42OSw5LjgxLDkuNzcsMTAuMy40My4yLDEuNjQuMjUsMS40OC0uNDktMzEuNzMtMzkuNzgtODMuNTMtNTguNjMtMTMzLjk5LTUzLjUybDcuOTktMi45OGMtMTguMjUuMjEtMzcuNDcsNC40MS01NC41MiwxMC45Ny0yLjg2LjI4LS44Ny0xLjI5LjE2LTEuODUsMS4yMS0uNjUsMTQuNzItNS4xMiwxMy4zNy02LjEyLTE2LjY3LDMuNjUtMzMuMTIsMTEuNy00Ny41MiwyMC45Ny05LjE1LDUuODktMTUuODIsMTIuMTMtMjMuOTcsMTkuMDItMS4xMi45NS0xLjYzLDIuNDItMy41LDEuOTksMy42My0zLjQyLDQuMzEtNy41Myw3LjgyLTEwLjksNS40Mi01LjIyLDE2LjA3LTEzLjEzLDIyLjQ0LTE3LjM5LDMyLjA3LTIxLjQ1LDY5LjEzLTMxLjM4LDEwNy43NC0zMC43MS0uNTMtMS41NS01LjAxLTEuNzktNi41MS0xLjk4LTMuOTEtLjQ5LTEyLjY5LjQ4LTE0LjgyLjAxLS43My0uMTYtLjYtMS45Mi0xLjMzLTIuMDYtMi45OC0uNTMtMTAuNzgsMS43LTE0LjMzLDEuMDItLjI0LTEuMzcsMS43OC0xLjUxLDIuNzUtMS43Miw2LjU5LTEuNDQsMTMuOTgtMS4xLDIwLjcyLTIuMzEsMS43Ny0uMzIsMi45OSwxLjEsMi41Mi0xLjk1bC0zOC45OSwzLjk4LDE2Ljk5LTQtNC45OS0xLjk4YzUyLjEyLTcuOTIsMTA0LjI4LDcuNzMsMTQ1LjU5LDM5LjRaIi8+CiAgICAgICAgICA8cGF0aCBkPSJNODAuODksMzQ2LjAxYy00LjUyLjUxLTMuNDQtMi45NC00LjEtMy44Ni0uMTItLjE2LTEuNDMuNTMtMS45MS4yNC0zLjE0LTEuODktMy4yMi02LjEzLTMuMDEtOS4zN2wtMS45OCwxLjk5LTIuMDItMy41MWMxLjk1LS44LDIuMjktMS4yMSwyLjAxLTMuNDhsMTAuOTksMTcuOThaIi8+CiAgICAgICAgPC9nPgogICAgICA8L2c+CiAgICA8L2c+CiAgPC9nPgo8L3N2Zz4=";
@@ -6532,7 +6677,7 @@ var useChatHeader = (config) => {
6532
6677
  const resolvedOnPin = useMemo4(() => resolveOnPin(config?.onPin), [config?.onPin]);
6533
6678
  const [isPinned, setIsPinned] = useState11(config?.alwaysOnTop ?? false);
6534
6679
  const isFirstRender = useRef6(true);
6535
- useEffect13(() => {
6680
+ useEffect14(() => {
6536
6681
  if (isFirstRender.current) {
6537
6682
  isFirstRender.current = false;
6538
6683
  return;
@@ -6565,7 +6710,7 @@ var useChatHeader = (config) => {
6565
6710
  // src/renderer/components/SanqianMessageList.tsx
6566
6711
  import {
6567
6712
  useRef as useRef8,
6568
- useEffect as useEffect15,
6713
+ useEffect as useEffect16,
6569
6714
  useCallback as useCallback13,
6570
6715
  useState as useState13,
6571
6716
  useMemo as useMemo7,
@@ -6582,7 +6727,7 @@ import { memo as memo3, useMemo as useMemo5, useCallback as useCallback11 } from
6582
6727
  import { Streamdown, defaultRehypePlugins, defaultRemarkPlugins } from "streamdown";
6583
6728
  import { harden } from "rehype-harden";
6584
6729
  import remarkGfm from "remark-gfm";
6585
- import { jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
6730
+ import { jsx as jsx6 } from "react/jsx-runtime";
6586
6731
  var PROSE_CLASSES = "prose prose-chat max-w-none";
6587
6732
  var DEFAULT_PROTOCOLS = ["workspace:", "download:"];
6588
6733
  function safeParseUrl(href) {
@@ -6642,13 +6787,6 @@ var MarkdownRenderer = memo3(function MarkdownRenderer2({
6642
6787
  const customComponents = useMemo5(() => {
6643
6788
  const comps = {};
6644
6789
  comps.p = ({ children }) => {
6645
- if (isStreaming && children && typeof children === "string" && children.endsWith("\u258C")) {
6646
- const textWithoutCursor = children.slice(0, -1);
6647
- return /* @__PURE__ */ jsxs2("p", { children: [
6648
- textWithoutCursor,
6649
- /* @__PURE__ */ jsx6("span", { style: { color: "var(--chat-accent)" }, className: "chat-cursor-breathing", children: "\u258C" })
6650
- ] });
6651
- }
6652
6790
  return /* @__PURE__ */ jsx6("p", { children });
6653
6791
  };
6654
6792
  const hasLinkHandler = onLinkClick || linkHandler?.onLinkClick || components?.a;
@@ -6691,20 +6829,32 @@ var MarkdownRenderer = memo3(function MarkdownRenderer2({
6691
6829
  }
6692
6830
  return comps;
6693
6831
  }, [components, isStreaming, handleLinkClick, onLinkClick, linkHandler]);
6694
- const displayContent = isStreaming ? content.replace(/\n+$/, "") + "\u258C" : content;
6695
- return /* @__PURE__ */ jsx6("div", { className: `${PROSE_CLASSES}${className ? ` ${className}` : ""}`, children: /* @__PURE__ */ jsx6(Streamdown, { remarkPlugins, rehypePlugins, components: customComponents, children: displayContent }) });
6832
+ const displayContent = isStreaming ? content.replace(/\n+$/, "") : content;
6833
+ const streamClassName = isStreaming ? "chat-streaming-cursor" : void 0;
6834
+ return /* @__PURE__ */ jsx6("div", { className: `${PROSE_CLASSES}${className ? ` ${className}` : ""}`, children: /* @__PURE__ */ jsx6(
6835
+ Streamdown,
6836
+ {
6837
+ remarkPlugins,
6838
+ rehypePlugins,
6839
+ components: customComponents,
6840
+ mode: isStreaming ? "streaming" : "static",
6841
+ isAnimating: isStreaming,
6842
+ className: streamClassName,
6843
+ children: displayContent
6844
+ }
6845
+ ) });
6696
6846
  });
6697
6847
 
6698
6848
  // src/renderer/components/IntermediateSteps.tsx
6699
- import { memo as memo5, useState as useState12, useRef as useRef7, useEffect as useEffect14, useCallback as useCallback12, useMemo as useMemo6 } from "react";
6849
+ import { memo as memo5, useState as useState12, useRef as useRef7, useEffect as useEffect15, useCallback as useCallback12, useMemo as useMemo6 } from "react";
6700
6850
 
6701
6851
  // src/renderer/renderers/ToolArgumentsDisplay.tsx
6702
6852
  import { memo as memo4 } from "react";
6703
- import { jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
6853
+ import { jsx as jsx7, jsxs as jsxs2 } from "react/jsx-runtime";
6704
6854
  function formatValue(value, indent = 0) {
6705
6855
  const indentStr = " ".repeat(indent);
6706
6856
  if (typeof value === "string") {
6707
- return /* @__PURE__ */ jsxs3("span", { className: "text-[var(--chat-text)]", children: [
6857
+ return /* @__PURE__ */ jsxs2("span", { className: "text-[var(--chat-text)]", children: [
6708
6858
  '"',
6709
6859
  value,
6710
6860
  '"'
@@ -6725,7 +6875,7 @@ function formatValue(value, indent = 0) {
6725
6875
  if (allPrimitives && inline.length <= 50) {
6726
6876
  return /* @__PURE__ */ jsx7("span", { className: "text-[var(--chat-text)]", children: inline });
6727
6877
  }
6728
- return /* @__PURE__ */ jsx7("div", { className: "text-[var(--chat-text)]", children: value.map((item, idx) => /* @__PURE__ */ jsxs3("div", { children: [
6878
+ return /* @__PURE__ */ jsx7("div", { className: "text-[var(--chat-text)]", children: value.map((item, idx) => /* @__PURE__ */ jsxs2("div", { children: [
6729
6879
  indentStr,
6730
6880
  "* ",
6731
6881
  formatValue(item, indent + 1)
@@ -6741,15 +6891,15 @@ function formatValue(value, indent = 0) {
6741
6891
  );
6742
6892
  const inline = JSON.stringify(value);
6743
6893
  if (allSimple && inline.length <= 50) {
6744
- return /* @__PURE__ */ jsx7("span", { className: "text-[var(--chat-text)]", children: objEntries.map(([k, v], idx) => /* @__PURE__ */ jsxs3("span", { children: [
6894
+ return /* @__PURE__ */ jsx7("span", { className: "text-[var(--chat-text)]", children: objEntries.map(([k, v], idx) => /* @__PURE__ */ jsxs2("span", { children: [
6745
6895
  idx > 0 && /* @__PURE__ */ jsx7("span", { className: "text-[var(--chat-muted)]", children: ", " }),
6746
6896
  /* @__PURE__ */ jsx7("span", { className: "text-[var(--chat-muted)]", children: k }),
6747
6897
  /* @__PURE__ */ jsx7("span", { children: "=" }),
6748
6898
  typeof v === "string" ? `"${v}"` : String(v)
6749
6899
  ] }, idx)) });
6750
6900
  }
6751
- return /* @__PURE__ */ jsx7("div", { className: "text-[var(--chat-text)]", children: objEntries.map(([k, v], idx) => /* @__PURE__ */ jsxs3("div", { className: "flex gap-1.5", children: [
6752
- /* @__PURE__ */ jsxs3("span", { className: "text-[var(--chat-muted)] shrink-0", children: [
6901
+ return /* @__PURE__ */ jsx7("div", { className: "text-[var(--chat-text)]", children: objEntries.map(([k, v], idx) => /* @__PURE__ */ jsxs2("div", { className: "flex gap-1.5", children: [
6902
+ /* @__PURE__ */ jsxs2("span", { className: "text-[var(--chat-muted)] shrink-0", children: [
6753
6903
  indentStr,
6754
6904
  k
6755
6905
  ] }),
@@ -6767,7 +6917,7 @@ var ToolArgumentsDisplay = memo4(function ToolArgumentsDisplay2({
6767
6917
  if (entries.length === 0) {
6768
6918
  return /* @__PURE__ */ jsx7("div", { className: `text-[var(--chat-muted)] italic${className ? ` ${className}` : ""}`, children: "No arguments" });
6769
6919
  }
6770
- return /* @__PURE__ */ jsx7("div", { className: `space-y-1 font-mono text-sm${className ? ` ${className}` : ""}`, children: entries.map(([key, value], idx) => /* @__PURE__ */ jsxs3("div", { className: "flex gap-1.5", children: [
6920
+ return /* @__PURE__ */ jsx7("div", { className: `space-y-1 font-mono text-sm${className ? ` ${className}` : ""}`, children: entries.map(([key, value], idx) => /* @__PURE__ */ jsxs2("div", { className: "flex gap-1.5", children: [
6771
6921
  /* @__PURE__ */ jsx7("span", { className: "text-[var(--chat-muted)] shrink-0", children: key }),
6772
6922
  /* @__PURE__ */ jsx7("span", { className: "text-[var(--chat-text)] shrink-0", children: "=" }),
6773
6923
  /* @__PURE__ */ jsx7("div", { className: "min-w-0 flex-1", children: formatValue(value, 1) })
@@ -6775,7 +6925,7 @@ var ToolArgumentsDisplay = memo4(function ToolArgumentsDisplay2({
6775
6925
  });
6776
6926
 
6777
6927
  // src/renderer/components/IntermediateSteps.tsx
6778
- import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
6928
+ import { jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
6779
6929
  var LOADING_SYMBOLS = ["\u2724", "\u2725", "\u2726", "\u2725", "\u2724"];
6780
6930
  function cleanToolName(name) {
6781
6931
  if (!name) return "";
@@ -6850,8 +7000,8 @@ function ToolCallItem({ toolCall, toolResult }) {
6850
7000
  const hasArgs = toolCall.toolArgs && Object.keys(toolCall.toolArgs).length > 0;
6851
7001
  const rawName = cleanToolName(toolCall.toolName);
6852
7002
  const displayName = rawName && !/^[{[]/.test(rawName.trim()) ? rawName : toolCall.toolCallId || "tool";
6853
- return /* @__PURE__ */ jsxs4("div", { children: [
6854
- /* @__PURE__ */ jsxs4(
7003
+ return /* @__PURE__ */ jsxs3("div", { children: [
7004
+ /* @__PURE__ */ jsxs3(
6855
7005
  "span",
6856
7006
  {
6857
7007
  onClick: () => setExpanded(!expanded),
@@ -6861,7 +7011,7 @@ function ToolCallItem({ toolCall, toolResult }) {
6861
7011
  /* @__PURE__ */ jsx8("span", { className: "font-mono", children: displayName }),
6862
7012
  toolResult && /* @__PURE__ */ jsx8("span", { className: "text-green-600 dark:text-green-400", children: TimelineIcons.check }),
6863
7013
  !toolResult && toolCall.toolStatus === "error" && /* @__PURE__ */ jsx8("span", { className: "text-red-500", children: TimelineIcons.error }),
6864
- hasArgs && !expanded && /* @__PURE__ */ jsxs4("span", { className: "font-mono", style: { color: "var(--chat-text)", opacity: 0.6, fontSize: "0.75rem" }, children: [
7014
+ hasArgs && !expanded && /* @__PURE__ */ jsxs3("span", { className: "font-mono", style: { color: "var(--chat-text)", opacity: 0.6, fontSize: "0.75rem" }, children: [
6865
7015
  "(",
6866
7016
  Object.values(toolCall.toolArgs).slice(0, 1).map((v) => typeof v === "string" ? v.length > 18 ? v.slice(0, 18) + "\u2026" : v : "\u2026"),
6867
7017
  ")"
@@ -6869,9 +7019,9 @@ function ToolCallItem({ toolCall, toolResult }) {
6869
7019
  ]
6870
7020
  }
6871
7021
  ),
6872
- expanded && /* @__PURE__ */ jsxs4("div", { className: "mt-1 ml-1 pl-2 space-y-1", style: { borderLeft: "1px solid var(--chat-border)", fontSize: "0.8125rem" }, children: [
7022
+ expanded && /* @__PURE__ */ jsxs3("div", { className: "mt-1 ml-1 pl-2 space-y-1", style: { borderLeft: "1px solid var(--chat-border)", fontSize: "0.8125rem" }, children: [
6873
7023
  hasArgs && /* @__PURE__ */ jsx8("div", { className: "font-mono", style: { color: "var(--chat-text)", opacity: 0.7 }, children: /* @__PURE__ */ jsx8(ToolArgumentsDisplay, { args: toolCall.toolArgs }) }),
6874
- toolResult && /* @__PURE__ */ jsxs4("pre", { className: "whitespace-pre-wrap font-mono max-h-24 overflow-y-auto m-0", style: { color: "var(--chat-text)", opacity: 0.6 }, children: [
7024
+ toolResult && /* @__PURE__ */ jsxs3("pre", { className: "whitespace-pre-wrap font-mono max-h-24 overflow-y-auto m-0", style: { color: "var(--chat-text)", opacity: 0.6 }, children: [
6875
7025
  toolResult.content.slice(0, 200),
6876
7026
  toolResult.content.length > 200 ? "\u2026" : ""
6877
7027
  ] })
@@ -6888,8 +7038,8 @@ function StreamingToolCallItem({
6888
7038
  const hasArgs = toolCall.toolArgs && Object.keys(toolCall.toolArgs).length > 0;
6889
7039
  const rawName = cleanToolName(toolCall.toolName);
6890
7040
  const displayName = rawName && !/^[{[]/.test(rawName.trim()) ? rawName : toolCall.toolCallId || "tool";
6891
- return /* @__PURE__ */ jsxs4("div", { children: [
6892
- /* @__PURE__ */ jsxs4(
7041
+ return /* @__PURE__ */ jsxs3("div", { children: [
7042
+ /* @__PURE__ */ jsxs3(
6893
7043
  "span",
6894
7044
  {
6895
7045
  onClick: () => setExpanded(!expanded),
@@ -6899,7 +7049,7 @@ function StreamingToolCallItem({
6899
7049
  /* @__PURE__ */ jsx8("span", { className: "font-mono", children: displayName }),
6900
7050
  toolResult && /* @__PURE__ */ jsx8("span", { className: "text-green-600 dark:text-green-400", children: TimelineIcons.check }),
6901
7051
  isActive && /* @__PURE__ */ jsx8("span", { className: "ml-0.5 text-amber-500 animate-pulse", children: "\u25C6" }),
6902
- hasArgs && !expanded && /* @__PURE__ */ jsxs4("span", { className: "font-mono", style: { color: "var(--chat-text)", opacity: 0.6, fontSize: "0.75rem" }, children: [
7052
+ hasArgs && !expanded && /* @__PURE__ */ jsxs3("span", { className: "font-mono", style: { color: "var(--chat-text)", opacity: 0.6, fontSize: "0.75rem" }, children: [
6903
7053
  "(",
6904
7054
  Object.values(toolCall.toolArgs).slice(0, 1).map((v) => typeof v === "string" ? v.length > 18 ? v.slice(0, 18) + "\u2026" : v : "\u2026"),
6905
7055
  ")"
@@ -6907,9 +7057,9 @@ function StreamingToolCallItem({
6907
7057
  ]
6908
7058
  }
6909
7059
  ),
6910
- expanded && /* @__PURE__ */ jsxs4("div", { className: "mt-1 ml-1 pl-2 space-y-1", style: { borderLeft: "1px solid var(--chat-border)", fontSize: "0.8125rem" }, children: [
7060
+ expanded && /* @__PURE__ */ jsxs3("div", { className: "mt-1 ml-1 pl-2 space-y-1", style: { borderLeft: "1px solid var(--chat-border)", fontSize: "0.8125rem" }, children: [
6911
7061
  hasArgs && /* @__PURE__ */ jsx8("div", { className: "font-mono", style: { color: "var(--chat-text)", opacity: 0.7 }, children: /* @__PURE__ */ jsx8(ToolArgumentsDisplay, { args: toolCall.toolArgs }) }),
6912
- toolResult && /* @__PURE__ */ jsxs4("pre", { className: "whitespace-pre-wrap font-mono max-h-24 overflow-y-auto m-0", style: { color: "var(--chat-text)", opacity: 0.6 }, children: [
7062
+ toolResult && /* @__PURE__ */ jsxs3("pre", { className: "whitespace-pre-wrap font-mono max-h-24 overflow-y-auto m-0", style: { color: "var(--chat-text)", opacity: 0.6 }, children: [
6913
7063
  toolResult.content.slice(0, 200),
6914
7064
  toolResult.content.length > 200 ? "\u2026" : ""
6915
7065
  ] }),
@@ -6970,7 +7120,7 @@ var ThinkingSection = memo5(function ThinkingSection2({
6970
7120
  const isExpanded = effectiveIsStreaming || effectiveIsPaused || manualExpanded;
6971
7121
  const displayContent = effectiveIsStreaming || effectiveIsPaused ? currentThinking || thinking : thinking;
6972
7122
  const hasContent = displayContent && displayContent.split("\n").filter((line) => line.trim() && !line.trim().match(/^─+$/)).length > 0;
6973
- useEffect14(() => {
7123
+ useEffect15(() => {
6974
7124
  if (effectiveIsStreaming) {
6975
7125
  const interval = setInterval(() => {
6976
7126
  setLoadingSymbolIndex((prev) => (prev + 1) % LOADING_SYMBOLS.length);
@@ -6978,13 +7128,13 @@ var ThinkingSection = memo5(function ThinkingSection2({
6978
7128
  return () => clearInterval(interval);
6979
7129
  }
6980
7130
  }, [effectiveIsStreaming]);
6981
- useEffect14(() => {
7131
+ useEffect15(() => {
6982
7132
  if (effectiveIsStreaming && isExpanded && contentRef.current && !isUserScrollingRef.current) {
6983
7133
  contentRef.current.scrollTop = contentRef.current.scrollHeight;
6984
7134
  }
6985
7135
  }, [displayContent, effectiveIsStreaming, isExpanded]);
6986
7136
  const prevManualExpandedRef = useRef7(manualExpanded);
6987
- useEffect14(() => {
7137
+ useEffect15(() => {
6988
7138
  const wasCollapsed = !prevManualExpandedRef.current;
6989
7139
  const isNowExpanded = manualExpanded;
6990
7140
  if (wasCollapsed && isNowExpanded && !effectiveIsStreaming && contentRef.current) {
@@ -6998,7 +7148,7 @@ var ThinkingSection = memo5(function ThinkingSection2({
6998
7148
  const isAtBottom = scrollHeight - scrollTop - clientHeight < 20;
6999
7149
  isUserScrollingRef.current = !isAtBottom;
7000
7150
  }, [effectiveIsStreaming]);
7001
- useEffect14(() => {
7151
+ useEffect15(() => {
7002
7152
  if (!effectiveIsStreaming) {
7003
7153
  isUserScrollingRef.current = false;
7004
7154
  }
@@ -7012,8 +7162,8 @@ var ThinkingSection = memo5(function ThinkingSection2({
7012
7162
  if (!hasContent) {
7013
7163
  return null;
7014
7164
  }
7015
- return /* @__PURE__ */ jsxs4("div", { className: `mb-3${className ? ` ${className}` : ""}`, children: [
7016
- /* @__PURE__ */ jsxs4(
7165
+ return /* @__PURE__ */ jsxs3("div", { className: `mb-3${className ? ` ${className}` : ""}`, children: [
7166
+ /* @__PURE__ */ jsxs3(
7017
7167
  "button",
7018
7168
  {
7019
7169
  onClick: handleToggle,
@@ -7027,7 +7177,7 @@ var ThinkingSection = memo5(function ThinkingSection2({
7027
7177
  },
7028
7178
  children: [
7029
7179
  /* @__PURE__ */ jsx8("span", { className: `text-[10px] transition-transform ${isExpanded ? "rotate-90" : ""}`, children: "\u25B6" }),
7030
- effectiveIsStreaming ? /* @__PURE__ */ jsxs4("span", { className: "flex items-center gap-1.5", children: [
7180
+ effectiveIsStreaming ? /* @__PURE__ */ jsxs3("span", { className: "flex items-center gap-1.5", children: [
7031
7181
  /* @__PURE__ */ jsx8("span", { className: "text-[var(--chat-accent)]", children: LOADING_SYMBOLS[loadingSymbolIndex] }),
7032
7182
  /* @__PURE__ */ jsx8("span", { children: strings.thinkingStreaming || "\u6B63\u5728\u601D\u8003..." })
7033
7183
  ] }) : effectiveIsPaused ? /* @__PURE__ */ jsx8("span", { children: strings.thinkingPaused || "\u5DF2\u601D\u8003" }) : /* @__PURE__ */ jsx8("span", { children: strings.thinking || "\u601D\u8003\u8FC7\u7A0B" })
@@ -7049,8 +7199,8 @@ var IntermediateSteps = memo5(function IntermediateSteps2({
7049
7199
  const stepCount = rounds.filter((round) => round.toolCalls.length > 0).length;
7050
7200
  if (stepCount === 0) return null;
7051
7201
  const summary = `${stepCount} ${strings.steps || "\u6B65"}`;
7052
- return /* @__PURE__ */ jsxs4("div", { className: `mb-3${className ? ` ${className}` : ""}`, children: [
7053
- /* @__PURE__ */ jsxs4(
7202
+ return /* @__PURE__ */ jsxs3("div", { className: `mb-3${className ? ` ${className}` : ""}`, children: [
7203
+ /* @__PURE__ */ jsxs3(
7054
7204
  "button",
7055
7205
  {
7056
7206
  onClick: () => setIsExpanded(!isExpanded),
@@ -7092,7 +7242,7 @@ var IntermediateSteps = memo5(function IntermediateSteps2({
7092
7242
  }
7093
7243
  }
7094
7244
  if (items.length === 0) return null;
7095
- return /* @__PURE__ */ jsxs4(
7245
+ return /* @__PURE__ */ jsxs3(
7096
7246
  "div",
7097
7247
  {
7098
7248
  className: "relative pl-5 opacity-90 hover:opacity-100 transition-opacity",
@@ -7110,8 +7260,8 @@ var IntermediateSteps = memo5(function IntermediateSteps2({
7110
7260
  ),
7111
7261
  /* @__PURE__ */ jsx8("div", { className: isLastRound ? "" : "pb-2", children: items.map((item, itemIdx) => {
7112
7262
  const isLastItem = itemIdx === items.length - 1;
7113
- return /* @__PURE__ */ jsxs4("div", { className: `flex items-baseline gap-1 ${isLastItem ? "" : "pb-1"}`, children: [
7114
- /* @__PURE__ */ jsxs4("span", { className: "flex-shrink-0 inline-flex", style: { color: "var(--chat-text)", opacity: 0.5, transform: "translateY(2px)" }, children: [
7263
+ return /* @__PURE__ */ jsxs3("div", { className: `flex items-baseline gap-1 ${isLastItem ? "" : "pb-1"}`, children: [
7264
+ /* @__PURE__ */ jsxs3("span", { className: "flex-shrink-0 inline-flex", style: { color: "var(--chat-text)", opacity: 0.5, transform: "translateY(2px)" }, children: [
7115
7265
  item.type === "thinking" && TimelineIcons.thinking,
7116
7266
  item.type === "text" && TimelineIcons.text,
7117
7267
  item.type === "tool" && TimelineIcons.tool
@@ -7210,20 +7360,20 @@ var StreamingTimeline = memo5(function StreamingTimeline2({
7210
7360
  const isAtBottom = scrollHeight - scrollTop - clientHeight < 20;
7211
7361
  isUserScrollingRef.current = !isAtBottom;
7212
7362
  }, []);
7213
- useEffect14(() => {
7363
+ useEffect15(() => {
7214
7364
  if (isExpanded && timelineRef.current && !isUserScrollingRef.current) {
7215
7365
  timelineRef.current.scrollTop = timelineRef.current.scrollHeight;
7216
7366
  }
7217
7367
  }, [displayRounds, isExpanded]);
7218
- useEffect14(() => {
7368
+ useEffect15(() => {
7219
7369
  if (!isThinkingActive && !isToolsActive) {
7220
7370
  isUserScrollingRef.current = false;
7221
7371
  }
7222
7372
  }, [isThinkingActive, isToolsActive]);
7223
7373
  if (displayRounds.length === 0) return null;
7224
7374
  if (stepCount === 0 && !isToolsActive) return null;
7225
- return /* @__PURE__ */ jsxs4("div", { className: `mb-3${className ? ` ${className}` : ""}`, children: [
7226
- /* @__PURE__ */ jsxs4(
7375
+ return /* @__PURE__ */ jsxs3("div", { className: `mb-3${className ? ` ${className}` : ""}`, children: [
7376
+ /* @__PURE__ */ jsxs3(
7227
7377
  "button",
7228
7378
  {
7229
7379
  onClick: () => setIsExpanded(!isExpanded),
@@ -7244,7 +7394,7 @@ var StreamingTimeline = memo5(function StreamingTimeline2({
7244
7394
  ),
7245
7395
  isExpanded && /* @__PURE__ */ jsx8("div", { ref: timelineRef, onScroll: handleScroll, className: "mt-2 ml-2 max-h-80 overflow-y-auto", children: displayRounds.map((items, roundIdx) => {
7246
7396
  const isLastRound = roundIdx === displayRounds.length - 1;
7247
- return /* @__PURE__ */ jsxs4(
7397
+ return /* @__PURE__ */ jsxs3(
7248
7398
  "div",
7249
7399
  {
7250
7400
  className: "relative pl-5 opacity-90 hover:opacity-100 transition-opacity",
@@ -7284,8 +7434,8 @@ var StreamingTimeline = memo5(function StreamingTimeline2({
7284
7434
  }
7285
7435
  );
7286
7436
  }
7287
- return /* @__PURE__ */ jsxs4("div", { className: `flex items-baseline gap-1 ${isLastItem ? "" : "pb-1"}`, children: [
7288
- /* @__PURE__ */ jsxs4("span", { className: "flex-shrink-0 inline-flex", style: { color: "var(--chat-text)", opacity: 0.5, transform: "translateY(2px)" }, children: [
7437
+ return /* @__PURE__ */ jsxs3("div", { className: `flex items-baseline gap-1 ${isLastItem ? "" : "pb-1"}`, children: [
7438
+ /* @__PURE__ */ jsxs3("span", { className: "flex-shrink-0 inline-flex", style: { color: "var(--chat-text)", opacity: 0.5, transform: "translateY(2px)" }, children: [
7289
7439
  item.type === "thinking" && TimelineIcons.thinking,
7290
7440
  item.type === "text" && TimelineIcons.text,
7291
7441
  item.type === "tool" && TimelineIcons.tool
@@ -7301,27 +7451,101 @@ var StreamingTimeline = memo5(function StreamingTimeline2({
7301
7451
  ] });
7302
7452
  });
7303
7453
 
7304
- // src/renderer/components/SanqianChatMessage.tsx
7305
- import { jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
7306
- var SanqianChatMessage = memo6(function SanqianChatMessage2({ message }) {
7307
- if (message.role === "tool") return null;
7454
+ // src/renderer/utils/intermediateDisplay.ts
7455
+ function normalizeToolResult(result) {
7456
+ if (result === void 0 || result === null) return void 0;
7457
+ if (typeof result === "string") {
7458
+ return result.trim() ? result : void 0;
7459
+ }
7460
+ try {
7461
+ return JSON.stringify(result, null, 2);
7462
+ } catch {
7463
+ return String(result);
7464
+ }
7465
+ }
7466
+ function buildFallbackBlocksFromToolCalls(toolCalls) {
7467
+ if (!toolCalls || toolCalls.length === 0) return void 0;
7468
+ const blocks = [];
7469
+ let timestamp = Date.now();
7470
+ for (const toolCall of toolCalls) {
7471
+ const toolStatus = toolCall.status || (toolCall.result !== void 0 ? "completed" : "running");
7472
+ blocks.push({
7473
+ type: "tool_call",
7474
+ content: "",
7475
+ timestamp: timestamp++,
7476
+ toolName: toolCall.name,
7477
+ toolArgs: toolCall.args,
7478
+ toolCallId: toolCall.id,
7479
+ toolStatus,
7480
+ isIntermediate: true
7481
+ });
7482
+ const resultContent = normalizeToolResult(toolCall.result);
7483
+ if (resultContent) {
7484
+ blocks.push({
7485
+ type: "tool_result",
7486
+ content: resultContent,
7487
+ timestamp: timestamp++,
7488
+ toolName: toolCall.name,
7489
+ toolCallId: toolCall.id,
7490
+ isIntermediate: true
7491
+ });
7492
+ }
7493
+ }
7494
+ return blocks.length > 0 ? blocks : void 0;
7495
+ }
7496
+ function getAssistantDisplayState(message) {
7308
7497
  const isUser = message.role === "user";
7309
- const hasToolCalls = (message.toolCalls?.length ?? 0) > 0;
7310
- const hasToolBlocks = message.blocks?.some((b) => b.type === "tool_call" || b.type === "tool_result") ?? false;
7498
+ const displayBlocks = message.blocks && message.blocks.length > 0 ? message.blocks : buildFallbackBlocksFromToolCalls(message.toolCalls);
7499
+ const hasToolCalls = Boolean(message.toolCalls && message.toolCalls.length > 0);
7500
+ const hasToolBlocks = Boolean(
7501
+ displayBlocks && displayBlocks.some((block) => block.type === "tool_call" || block.type === "tool_result")
7502
+ );
7311
7503
  const hasToolActivity = hasToolCalls || hasToolBlocks;
7312
- const hasIntermediateBlocks = message.blocks?.some((b) => b.isIntermediate) ?? false;
7313
- const showIntermediateSteps = Boolean(message.isComplete && hasIntermediateBlocks && hasToolActivity);
7314
- const showStreamingTimeline = Boolean(!isUser && !showIntermediateSteps && hasToolActivity);
7504
+ const hasRunningToolCalls = Boolean(
7505
+ message.toolCalls?.some((tool) => tool.status === "running") || displayBlocks?.some((block) => block.type === "tool_call" && block.toolStatus === "running")
7506
+ );
7507
+ const isEffectivelyComplete = Boolean(
7508
+ message.isComplete || !message.isStreaming && !message.isThinkingStreaming && !message.isToolCallsStreaming && !hasRunningToolCalls
7509
+ );
7510
+ const hasIntermediateBlocks = Boolean(displayBlocks?.some((block) => block.isIntermediate));
7315
7511
  const hasThinking = Boolean(message.thinking || message.isThinkingStreaming || message.currentThinking);
7512
+ const showIntermediateSteps = Boolean(
7513
+ !isUser && isEffectivelyComplete && hasToolActivity && hasIntermediateBlocks
7514
+ );
7515
+ const showStreamingTimeline = Boolean(!isUser && !showIntermediateSteps && hasToolActivity);
7316
7516
  const showThinkingSection = Boolean(!isUser && !hasToolActivity && !showIntermediateSteps && hasThinking);
7317
- const isToolCallsStreaming = (message.isToolCallsStreaming ?? (message.toolCalls?.some((tc) => tc.status === "running") ?? false)) || (message.blocks?.some((b) => b.type === "tool_call" && b.toolStatus === "running") ?? false);
7318
- const isThinkingPaused = message.isThinkingPaused ?? Boolean(!message.isThinkingStreaming && message.currentThinking && !message.isComplete);
7517
+ return {
7518
+ displayBlocks,
7519
+ hasToolActivity,
7520
+ isEffectivelyComplete,
7521
+ showIntermediateSteps,
7522
+ showStreamingTimeline,
7523
+ showThinkingSection
7524
+ };
7525
+ }
7526
+
7527
+ // src/renderer/components/SanqianChatMessage.tsx
7528
+ import { jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
7529
+ var SanqianChatMessage = memo6(function SanqianChatMessage2({ message }) {
7530
+ if (message.role === "tool") return null;
7531
+ const isUser = message.role === "user";
7532
+ const {
7533
+ displayBlocks,
7534
+ isEffectivelyComplete,
7535
+ showIntermediateSteps,
7536
+ showStreamingTimeline,
7537
+ showThinkingSection
7538
+ } = getAssistantDisplayState(message);
7539
+ const isToolCallsStreaming = (message.isToolCallsStreaming ?? (message.toolCalls?.some((tc) => tc.status === "running") ?? false)) || (displayBlocks?.some((b) => b.type === "tool_call" && b.toolStatus === "running") ?? false);
7540
+ const isThinkingPaused = message.isThinkingPaused ?? Boolean(!message.isThinkingStreaming && message.currentThinking && !isEffectivelyComplete);
7319
7541
  const showStreamingPlaceholder = Boolean(
7320
7542
  !isUser && message.isStreaming && !message.content && !showStreamingTimeline && !showIntermediateSteps
7321
7543
  );
7322
7544
  const hasAttachedResources = isUser && message.attachedResources && message.attachedResources.length > 0;
7323
- return /* @__PURE__ */ jsx9("div", { className: `flex ${isUser ? "justify-end" : "justify-start"} mb-4`, children: /* @__PURE__ */ jsxs5("div", { className: `text-left ${isUser ? "max-w-[80%]" : "w-full"}`, children: [
7324
- !isUser && showIntermediateSteps && message.blocks && /* @__PURE__ */ jsx9(IntermediateSteps, { blocks: message.blocks }),
7545
+ const hasUserText = isUser && message.content.trim().length > 0;
7546
+ const shouldRenderBubble = !isUser || hasUserText;
7547
+ return /* @__PURE__ */ jsx9("div", { className: `flex ${isUser ? "justify-end" : "justify-start"} mb-4`, children: /* @__PURE__ */ jsxs4("div", { className: `text-left ${isUser ? "max-w-[80%]" : "w-full"}`, children: [
7548
+ !isUser && showIntermediateSteps && displayBlocks && /* @__PURE__ */ jsx9(IntermediateSteps, { blocks: displayBlocks }),
7325
7549
  showThinkingSection && /* @__PURE__ */ jsx9(
7326
7550
  ThinkingSection,
7327
7551
  {
@@ -7329,26 +7553,26 @@ var SanqianChatMessage = memo6(function SanqianChatMessage2({ message }) {
7329
7553
  currentThinking: message.currentThinking,
7330
7554
  isStreaming: message.isThinkingStreaming,
7331
7555
  isPaused: isThinkingPaused,
7332
- isComplete: message.isComplete
7556
+ isComplete: isEffectivelyComplete
7333
7557
  }
7334
7558
  ),
7335
- showStreamingTimeline && message.blocks && /* @__PURE__ */ jsx9(
7559
+ showStreamingTimeline && displayBlocks && /* @__PURE__ */ jsx9(
7336
7560
  StreamingTimeline,
7337
7561
  {
7338
- blocks: message.blocks,
7562
+ blocks: displayBlocks,
7339
7563
  currentThinking: message.currentThinking,
7340
7564
  isThinkingStreaming: message.isThinkingStreaming,
7341
7565
  isToolCallsStreaming,
7342
- isComplete: message.isComplete
7566
+ isComplete: isEffectivelyComplete
7343
7567
  }
7344
7568
  ),
7345
7569
  hasAttachedResources && /* @__PURE__ */ jsx9(MessageAttachedResources, { resources: message.attachedResources }),
7346
- /* @__PURE__ */ jsx9("div", { className: `relative group ${isUser ? "inline-block max-w-full" : "block w-full"}`, children: /* @__PURE__ */ jsx9(
7570
+ shouldRenderBubble && /* @__PURE__ */ jsx9("div", { className: `relative group ${isUser ? "inline-block max-w-full" : "block w-full"}`, children: /* @__PURE__ */ jsx9(
7347
7571
  "div",
7348
7572
  {
7349
7573
  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"}`,
7350
- children: isUser ? /* @__PURE__ */ jsx9("span", { className: "whitespace-pre-wrap", children: message.content }) : message.content ? /* @__PURE__ */ jsx9(MarkdownRenderer, { content: message.content, isStreaming: message.isStreaming, className: "px-3" }) : showStreamingPlaceholder ? /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2 text-[var(--chat-muted)] italic min-h-[1.5rem]", children: [
7351
- /* @__PURE__ */ jsxs5("div", { className: "flex gap-1 items-center", children: [
7574
+ children: isUser ? /* @__PURE__ */ jsx9("span", { className: "whitespace-pre-wrap", children: message.content }) : message.content ? /* @__PURE__ */ jsx9(MarkdownRenderer, { content: message.content, isStreaming: message.isStreaming, className: "px-3" }) : showStreamingPlaceholder ? /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2 text-[var(--chat-muted)] italic min-h-[1.5rem]", children: [
7575
+ /* @__PURE__ */ jsxs4("div", { className: "flex gap-1 items-center", children: [
7352
7576
  /* @__PURE__ */ jsx9("span", { className: "w-1.5 h-1.5 bg-[var(--chat-accent)] rounded-full animate-bounce", style: { animationDelay: "0ms" } }),
7353
7577
  /* @__PURE__ */ jsx9("span", { className: "w-1.5 h-1.5 bg-[var(--chat-accent)] rounded-full animate-bounce", style: { animationDelay: "150ms" } }),
7354
7578
  /* @__PURE__ */ jsx9("span", { className: "w-1.5 h-1.5 bg-[var(--chat-accent)] rounded-full animate-bounce", style: { animationDelay: "300ms" } })
@@ -7362,7 +7586,7 @@ var SanqianChatMessage = memo6(function SanqianChatMessage2({ message }) {
7362
7586
  var MessageAttachedResources = memo6(function MessageAttachedResources2({
7363
7587
  resources
7364
7588
  }) {
7365
- return /* @__PURE__ */ jsx9("div", { className: "flex flex-wrap gap-1.5 mb-2 justify-end", children: resources.map((resource, index) => /* @__PURE__ */ jsxs5(
7589
+ return /* @__PURE__ */ jsx9("div", { className: "flex flex-wrap gap-1.5 mb-2 justify-end", children: resources.map((resource, index) => /* @__PURE__ */ jsxs4(
7366
7590
  "div",
7367
7591
  {
7368
7592
  className: "inline-flex items-center gap-1 px-2 py-1 text-xs rounded-full bg-[var(--chat-surface)] text-[var(--chat-muted)] border border-[var(--chat-border)]",
@@ -7383,7 +7607,7 @@ var INCREASE_VIEWPORT_BY = { top: 1500, bottom: 1500 };
7383
7607
  function ResizeAwareMessage({ message, onHeightChange }) {
7384
7608
  const containerRef = useRef8(null);
7385
7609
  const prevHeightRef = useRef8(0);
7386
- useEffect15(() => {
7610
+ useEffect16(() => {
7387
7611
  const container = containerRef.current;
7388
7612
  if (!container || !onHeightChange) return;
7389
7613
  let rafId = null;
@@ -7468,7 +7692,7 @@ var SanqianMessageList = forwardRef(
7468
7692
  }),
7469
7693
  [scrollToBottom]
7470
7694
  );
7471
- useEffect15(() => {
7695
+ useEffect16(() => {
7472
7696
  return () => {
7473
7697
  if (manualScrollTimeoutRef.current) {
7474
7698
  clearTimeout(manualScrollTimeoutRef.current);
@@ -7548,11 +7772,11 @@ import {
7548
7772
  useState as useState14,
7549
7773
  useRef as useRef9,
7550
7774
  useCallback as useCallback14,
7551
- useEffect as useEffect16,
7775
+ useEffect as useEffect17,
7552
7776
  forwardRef as forwardRef2,
7553
7777
  useImperativeHandle as useImperativeHandle2
7554
7778
  } from "react";
7555
- import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
7779
+ import { jsx as jsx11, jsxs as jsxs5 } from "react/jsx-runtime";
7556
7780
  var ChatInput = memo7(
7557
7781
  forwardRef2(function ChatInput2({
7558
7782
  onSend,
@@ -7561,6 +7785,7 @@ var ChatInput = memo7(
7561
7785
  disabled = false,
7562
7786
  isStreaming = false,
7563
7787
  isLoading = false,
7788
+ allowEmptySubmit = false,
7564
7789
  sendLabel = "Send",
7565
7790
  stopLabel = "Stop",
7566
7791
  autoFocus = false,
@@ -7571,7 +7796,8 @@ var ChatInput = memo7(
7571
7796
  }, ref) {
7572
7797
  const [text, setText] = useState14("");
7573
7798
  const textareaRef = useRef9(null);
7574
- const canSend = text.trim().length > 0 && !disabled && !isLoading;
7799
+ const submitInFlightRef = useRef9(false);
7800
+ const canSend = (text.trim().length > 0 || allowEmptySubmit) && !disabled && !isLoading;
7575
7801
  const showStopButton = isStreaming && !!onStop;
7576
7802
  const showSpinner = isLoading && !showStopButton;
7577
7803
  useImperativeHandle2(
@@ -7584,18 +7810,27 @@ var ChatInput = memo7(
7584
7810
  }),
7585
7811
  [text]
7586
7812
  );
7587
- useEffect16(() => {
7813
+ useEffect17(() => {
7588
7814
  if (autoFocus) {
7589
7815
  const timer = setTimeout(() => textareaRef.current?.focus(), 100);
7590
7816
  return () => clearTimeout(timer);
7591
7817
  }
7592
7818
  }, [autoFocus]);
7593
7819
  const handleSubmit = useCallback14(
7594
- (e) => {
7820
+ async (e) => {
7595
7821
  e?.preventDefault();
7596
7822
  if (!canSend) return;
7597
- onSend(text.trim());
7598
- setText("");
7823
+ if (submitInFlightRef.current) return;
7824
+ submitInFlightRef.current = true;
7825
+ try {
7826
+ const result = await onSend(text.trim());
7827
+ if (result !== false) {
7828
+ setText("");
7829
+ }
7830
+ } catch {
7831
+ } finally {
7832
+ submitInFlightRef.current = false;
7833
+ }
7599
7834
  },
7600
7835
  [text, canSend, onSend]
7601
7836
  );
@@ -7603,7 +7838,7 @@ var ChatInput = memo7(
7603
7838
  (e) => {
7604
7839
  if (e.key === "Enter" && !e.shiftKey && !e.nativeEvent.isComposing) {
7605
7840
  e.preventDefault();
7606
- handleSubmit();
7841
+ void handleSubmit();
7607
7842
  }
7608
7843
  if (e.key === "Escape" && showStopButton) {
7609
7844
  e.preventDefault();
@@ -7614,61 +7849,71 @@ var ChatInput = memo7(
7614
7849
  );
7615
7850
  const leftPadding = leftSlot ? "2rem" : "0.75rem";
7616
7851
  const rightPadding = rightSlot ? "2.5rem" : "0.75rem";
7617
- return /* @__PURE__ */ jsxs6("form", { onSubmit: handleSubmit, className: `chat-input-form${className ? ` ${className}` : ""}`, style, children: [
7618
- /* @__PURE__ */ jsxs6("div", { className: "chat-input-box", children: [
7619
- /* @__PURE__ */ jsx11(
7620
- "div",
7621
- {
7622
- className: "chat-input-replica",
7623
- style: { paddingLeft: leftPadding, paddingRight: rightPadding },
7624
- "aria-hidden": "true",
7625
- children: text + " "
7626
- }
7627
- ),
7628
- /* @__PURE__ */ jsx11(
7629
- "textarea",
7630
- {
7631
- ref: textareaRef,
7632
- value: text,
7633
- onChange: (e) => setText(e.target.value),
7634
- onKeyDown: handleKeyDown,
7635
- placeholder,
7636
- disabled,
7637
- rows: 1,
7638
- className: "chat-input-textarea",
7639
- style: { paddingLeft: leftPadding, paddingRight: rightPadding }
7640
- }
7641
- ),
7642
- leftSlot && /* @__PURE__ */ jsx11("div", { className: "chat-input-left-slot", children: leftSlot }),
7643
- rightSlot && /* @__PURE__ */ jsx11("div", { className: "chat-input-right-slot", children: rightSlot })
7644
- ] }),
7645
- /* @__PURE__ */ jsxs6("div", { className: "chat-input-send-wrapper", children: [
7646
- /* @__PURE__ */ jsx11(
7647
- "button",
7648
- {
7649
- type: showStopButton ? "button" : "submit",
7650
- onClick: showStopButton ? onStop : void 0,
7651
- disabled: !showStopButton && !canSend,
7652
- className: "chat-input-send-btn",
7653
- "aria-label": showStopButton ? stopLabel : sendLabel,
7654
- children: showSpinner ? /* @__PURE__ */ jsxs6("svg", { viewBox: "0 0 24 24", fill: "none", className: "animate-spin", children: [
7655
- /* @__PURE__ */ jsx11("circle", { cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4", opacity: "0.25" }),
7656
- /* @__PURE__ */ jsx11("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" })
7657
- ] }) : showStopButton ? /* @__PURE__ */ jsx11("svg", { viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx11("rect", { x: "6", y: "6", width: "12", height: "12", rx: "2" }) }) : /* @__PURE__ */ jsx11("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: /* @__PURE__ */ jsx11("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M4.5 10.5 12 3m0 0 7.5 7.5M12 3v18" }) })
7658
- }
7659
- ),
7660
- showStopButton && /* @__PURE__ */ jsxs6("div", { className: "chat-input-stop-tooltip", role: "note", children: [
7661
- /* @__PURE__ */ jsx11("div", { children: stopLabel }),
7662
- /* @__PURE__ */ jsx11("div", { className: "chat-input-stop-hotkey", children: "Esc" })
7663
- ] })
7664
- ] })
7665
- ] });
7852
+ return /* @__PURE__ */ jsxs5(
7853
+ "form",
7854
+ {
7855
+ onSubmit: (e) => {
7856
+ void handleSubmit(e);
7857
+ },
7858
+ className: `chat-input-form${className ? ` ${className}` : ""}`,
7859
+ style,
7860
+ children: [
7861
+ /* @__PURE__ */ jsxs5("div", { className: "chat-input-box", children: [
7862
+ /* @__PURE__ */ jsx11(
7863
+ "div",
7864
+ {
7865
+ className: "chat-input-replica",
7866
+ style: { paddingLeft: leftPadding, paddingRight: rightPadding },
7867
+ "aria-hidden": "true",
7868
+ children: text + " "
7869
+ }
7870
+ ),
7871
+ /* @__PURE__ */ jsx11(
7872
+ "textarea",
7873
+ {
7874
+ ref: textareaRef,
7875
+ value: text,
7876
+ onChange: (e) => setText(e.target.value),
7877
+ onKeyDown: handleKeyDown,
7878
+ placeholder,
7879
+ disabled,
7880
+ rows: 1,
7881
+ className: "chat-input-textarea",
7882
+ style: { paddingLeft: leftPadding, paddingRight: rightPadding }
7883
+ }
7884
+ ),
7885
+ leftSlot && /* @__PURE__ */ jsx11("div", { className: "chat-input-left-slot", children: leftSlot }),
7886
+ rightSlot && /* @__PURE__ */ jsx11("div", { className: "chat-input-right-slot", children: rightSlot })
7887
+ ] }),
7888
+ /* @__PURE__ */ jsxs5("div", { className: "chat-input-send-wrapper", children: [
7889
+ /* @__PURE__ */ jsx11(
7890
+ "button",
7891
+ {
7892
+ type: showStopButton ? "button" : "submit",
7893
+ onClick: showStopButton ? onStop : void 0,
7894
+ disabled: !showStopButton && !canSend,
7895
+ className: "chat-input-send-btn",
7896
+ "aria-label": showStopButton ? stopLabel : sendLabel,
7897
+ children: showSpinner ? /* @__PURE__ */ jsxs5("svg", { viewBox: "0 0 24 24", fill: "none", className: "animate-spin", children: [
7898
+ /* @__PURE__ */ jsx11("circle", { cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4", opacity: "0.25" }),
7899
+ /* @__PURE__ */ jsx11("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" })
7900
+ ] }) : showStopButton ? /* @__PURE__ */ jsx11("svg", { viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx11("rect", { x: "6", y: "6", width: "12", height: "12", rx: "2" }) }) : /* @__PURE__ */ jsx11("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: /* @__PURE__ */ jsx11("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M4.5 10.5 12 3m0 0 7.5 7.5M12 3v18" }) })
7901
+ }
7902
+ ),
7903
+ showStopButton && /* @__PURE__ */ jsxs5("div", { className: "chat-input-stop-tooltip", role: "note", children: [
7904
+ /* @__PURE__ */ jsx11("div", { children: stopLabel }),
7905
+ /* @__PURE__ */ jsx11("div", { className: "chat-input-stop-hotkey", children: "Esc" })
7906
+ ] })
7907
+ ] })
7908
+ ]
7909
+ }
7910
+ );
7666
7911
  })
7667
7912
  );
7668
7913
 
7669
7914
  // src/renderer/components/HitlCard.tsx
7670
- import { memo as memo8, useState as useState15, useEffect as useEffect17, useRef as useRef10 } from "react";
7671
- import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
7915
+ import { memo as memo8, useState as useState15, useEffect as useEffect18, useRef as useRef10 } from "react";
7916
+ import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
7672
7917
  var defaultStrings = {
7673
7918
  approve: "Approve",
7674
7919
  reject: "Reject",
@@ -7727,7 +7972,7 @@ var HitlCard = memo8(function HitlCard2({
7727
7972
  const textareaRef = useRef10(null);
7728
7973
  const riskLevel = interrupt.risk_level || "medium";
7729
7974
  const riskStyle = riskColors[riskLevel];
7730
- useEffect17(() => {
7975
+ useEffect18(() => {
7731
7976
  if (isUserInput) {
7732
7977
  if (!interrupt.options || interrupt.options.length === 0) {
7733
7978
  inputRef.current?.focus();
@@ -7735,7 +7980,7 @@ var HitlCard = memo8(function HitlCard2({
7735
7980
  }
7736
7981
  }
7737
7982
  }, [isUserInput, interrupt.options]);
7738
- useEffect17(() => {
7983
+ useEffect18(() => {
7739
7984
  if (timeLeft === null || timeLeft <= 0) return;
7740
7985
  const timer = setInterval(() => {
7741
7986
  setTimeLeft((prev) => {
@@ -7803,7 +8048,7 @@ var HitlCard = memo8(function HitlCard2({
7803
8048
  const textSecondary = isDarkMode ? "text-zinc-400" : "text-zinc-500";
7804
8049
  const inputBg = isDarkMode ? "bg-zinc-900" : "bg-zinc-50";
7805
8050
  const inputBorder = isDarkMode ? "border-zinc-600" : "border-zinc-300";
7806
- return /* @__PURE__ */ jsxs7(
8051
+ return /* @__PURE__ */ jsxs6(
7807
8052
  "div",
7808
8053
  {
7809
8054
  className: `rounded-xl border ${cardBorder} ${cardBg} p-3 shadow-sm`,
@@ -7811,8 +8056,8 @@ var HitlCard = memo8(function HitlCard2({
7811
8056
  "aria-modal": "true",
7812
8057
  "aria-label": isApproval ? t.approvalRequest : t.inputRequest,
7813
8058
  children: [
7814
- /* @__PURE__ */ jsxs7("div", { className: "mb-2 flex items-start justify-between gap-2", children: [
7815
- /* @__PURE__ */ jsx12("div", { className: "flex min-w-0 items-center gap-2", children: isApproval ? /* @__PURE__ */ jsxs7(
8059
+ /* @__PURE__ */ jsxs6("div", { className: "mb-2 flex items-start justify-between gap-2", children: [
8060
+ /* @__PURE__ */ jsx12("div", { className: "flex min-w-0 items-center gap-2", children: isApproval ? /* @__PURE__ */ jsxs6(
7816
8061
  "span",
7817
8062
  {
7818
8063
  className: `inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs font-medium ${riskStyle.bg} ${riskStyle.border} ${riskStyle.text} border`,
@@ -7822,27 +8067,27 @@ var HitlCard = memo8(function HitlCard2({
7822
8067
  ]
7823
8068
  }
7824
8069
  ) : /* @__PURE__ */ jsx12("span", { className: "text-lg", children: "?" }) }),
7825
- timeLeft !== null && timeLeft > 0 && /* @__PURE__ */ jsxs7("span", { className: `text-xs ${textSecondary} whitespace-nowrap`, children: [
8070
+ timeLeft !== null && timeLeft > 0 && /* @__PURE__ */ jsxs6("span", { className: `text-xs ${textSecondary} whitespace-nowrap`, children: [
7826
8071
  t.timeoutIn,
7827
8072
  " ",
7828
8073
  timeLeft,
7829
8074
  t.seconds
7830
8075
  ] })
7831
8076
  ] }),
7832
- /* @__PURE__ */ jsxs7("div", { className: "space-y-2", children: [
8077
+ /* @__PURE__ */ jsxs6("div", { className: "space-y-2", children: [
7833
8078
  /* @__PURE__ */ jsx12("p", { className: `text-sm font-medium ${textPrimary} break-words`, children: isApproval ? interrupt.reason || `${t.executeTool} ${interrupt.tool}?` : interrupt.question }),
7834
8079
  isUserInput && interrupt.context && /* @__PURE__ */ jsx12("div", { className: `text-xs ${textSecondary} rounded p-2 ${inputBg} break-words`, children: interrupt.context }),
7835
- isApproval && interrupt.tool && /* @__PURE__ */ jsxs7("div", { className: `text-xs ${textSecondary} rounded p-2 ${inputBg} space-y-1`, children: [
7836
- /* @__PURE__ */ jsxs7("div", { children: [
7837
- /* @__PURE__ */ jsxs7("span", { className: "font-medium", children: [
8080
+ isApproval && interrupt.tool && /* @__PURE__ */ jsxs6("div", { className: `text-xs ${textSecondary} rounded p-2 ${inputBg} space-y-1`, children: [
8081
+ /* @__PURE__ */ jsxs6("div", { children: [
8082
+ /* @__PURE__ */ jsxs6("span", { className: "font-medium", children: [
7838
8083
  t.toolLabel,
7839
8084
  ":"
7840
8085
  ] }),
7841
8086
  " ",
7842
8087
  interrupt.tool
7843
8088
  ] }),
7844
- interrupt.args && Object.keys(interrupt.args).length > 0 && /* @__PURE__ */ jsxs7("div", { className: "break-all", children: [
7845
- /* @__PURE__ */ jsxs7("span", { className: "font-medium", children: [
8089
+ interrupt.args && Object.keys(interrupt.args).length > 0 && /* @__PURE__ */ jsxs6("div", { className: "break-all", children: [
8090
+ /* @__PURE__ */ jsxs6("span", { className: "font-medium", children: [
7846
8091
  t.argsLabel,
7847
8092
  ":"
7848
8093
  ] }),
@@ -7850,7 +8095,7 @@ var HitlCard = memo8(function HitlCard2({
7850
8095
  /* @__PURE__ */ jsx12("code", { className: "text-[10px]", children: JSON.stringify(interrupt.args, null, 0) })
7851
8096
  ] })
7852
8097
  ] }),
7853
- isUserInput && interrupt.options && interrupt.options.length > 0 && /* @__PURE__ */ jsx12("div", { className: "space-y-1.5", children: interrupt.options.map((option, index) => /* @__PURE__ */ jsxs7(
8098
+ isUserInput && interrupt.options && interrupt.options.length > 0 && /* @__PURE__ */ jsx12("div", { className: "space-y-1.5", children: interrupt.options.map((option, index) => /* @__PURE__ */ jsxs6(
7854
8099
  "label",
7855
8100
  {
7856
8101
  className: `flex cursor-pointer items-center gap-2 rounded p-2 transition-colors ${selectedIndices.includes(index) ? isDarkMode ? "border-blue-500/50 bg-blue-500/20" : "border-blue-200 bg-blue-50" : `${inputBg} border-transparent hover:border-zinc-300`} border`,
@@ -7870,7 +8115,7 @@ var HitlCard = memo8(function HitlCard2({
7870
8115
  },
7871
8116
  index
7872
8117
  )) }),
7873
- isUserInput && (!interrupt.options || interrupt.options.length === 0) && /* @__PURE__ */ jsxs7("div", { children: [
8118
+ isUserInput && (!interrupt.options || interrupt.options.length === 0) && /* @__PURE__ */ jsxs6("div", { children: [
7874
8119
  /* @__PURE__ */ jsx12(
7875
8120
  "input",
7876
8121
  {
@@ -7887,7 +8132,7 @@ var HitlCard = memo8(function HitlCard2({
7887
8132
  ),
7888
8133
  interrupt.required && !answer.trim() && /* @__PURE__ */ jsx12("p", { className: "mt-1 text-xs text-red-500", children: t.requiredField })
7889
8134
  ] }),
7890
- isApproval && /* @__PURE__ */ jsxs7(
8135
+ isApproval && /* @__PURE__ */ jsxs6(
7891
8136
  "label",
7892
8137
  {
7893
8138
  className: "flex cursor-pointer items-center gap-2 text-xs",
@@ -7907,7 +8152,7 @@ var HitlCard = memo8(function HitlCard2({
7907
8152
  }
7908
8153
  )
7909
8154
  ] }),
7910
- /* @__PURE__ */ jsxs7("div", { className: "mt-3 flex gap-2", children: [
8155
+ /* @__PURE__ */ jsxs6("div", { className: "mt-3 flex gap-2", children: [
7911
8156
  /* @__PURE__ */ jsx12(
7912
8157
  "button",
7913
8158
  {
@@ -7934,7 +8179,7 @@ var HitlCard = memo8(function HitlCard2({
7934
8179
 
7935
8180
  // src/renderer/primitives/AlertBanner.tsx
7936
8181
  import { memo as memo9, useState as useState16 } from "react";
7937
- import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
8182
+ import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
7938
8183
  var AlertBanner = memo9(function AlertBanner2({
7939
8184
  type,
7940
8185
  message,
@@ -7948,13 +8193,13 @@ var AlertBanner = memo9(function AlertBanner2({
7948
8193
  const [isExpanded, setIsExpanded] = useState16(false);
7949
8194
  const defaultIcon = type === "error" ? (
7950
8195
  // Error icon (circle with X)
7951
- /* @__PURE__ */ jsxs8("svg", { className: "size-4 shrink-0", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
8196
+ /* @__PURE__ */ jsxs7("svg", { className: "size-4 shrink-0", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
7952
8197
  /* @__PURE__ */ jsx13("circle", { cx: "12", cy: "12", r: "10" }),
7953
8198
  /* @__PURE__ */ jsx13("path", { d: "M15 9l-6 6M9 9l6 6", strokeLinecap: "round" })
7954
8199
  ] })
7955
8200
  ) : (
7956
8201
  // Warning icon (triangle with !)
7957
- /* @__PURE__ */ jsxs8("svg", { className: "size-4 shrink-0", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
8202
+ /* @__PURE__ */ jsxs7("svg", { className: "size-4 shrink-0", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
7958
8203
  /* @__PURE__ */ jsx13(
7959
8204
  "path",
7960
8205
  {
@@ -7972,9 +8217,9 @@ var AlertBanner = memo9(function AlertBanner2({
7972
8217
  const lines = messageText.split("\n");
7973
8218
  const needsTruncation = isStringMessage && lines.length > maxLines;
7974
8219
  const truncatedMessage = needsTruncation && !isExpanded ? lines.slice(0, maxLines).join("\n") + "..." : messageText;
7975
- return /* @__PURE__ */ jsxs8("div", { className, role: "alert", "aria-live": "polite", "data-alert-type": type, children: [
8220
+ return /* @__PURE__ */ jsxs7("div", { className, role: "alert", "aria-live": "polite", "data-alert-type": type, children: [
7976
8221
  /* @__PURE__ */ jsx13("div", { className: "self-start pt-0.5", children: icon || defaultIcon }),
7977
- /* @__PURE__ */ jsxs8(
8222
+ /* @__PURE__ */ jsxs7(
7978
8223
  "span",
7979
8224
  {
7980
8225
  className: `flex-1 whitespace-pre-wrap break-words ${needsTruncation ? "cursor-pointer" : ""}`,
@@ -7985,7 +8230,7 @@ var AlertBanner = memo9(function AlertBanner2({
7985
8230
  ]
7986
8231
  }
7987
8232
  ),
7988
- /* @__PURE__ */ jsxs8("div", { className: "flex items-center self-start", children: [
8233
+ /* @__PURE__ */ jsxs7("div", { className: "flex items-center self-start", children: [
7989
8234
  action && /* @__PURE__ */ jsx13(
7990
8235
  "button",
7991
8236
  {
@@ -8010,11 +8255,11 @@ var AlertBanner = memo9(function AlertBanner2({
8010
8255
  });
8011
8256
 
8012
8257
  // src/renderer/components/AddResourceButton.tsx
8013
- import { memo as memo11, useState as useState18, useRef as useRef12, useEffect as useEffect19, useCallback as useCallback16 } from "react";
8258
+ import { memo as memo11, useState as useState18, useRef as useRef12, useEffect as useEffect20, useCallback as useCallback16 } from "react";
8014
8259
 
8015
8260
  // src/renderer/components/ResourcePicker.tsx
8016
- import { memo as memo10, useState as useState17, useCallback as useCallback15, useRef as useRef11, useEffect as useEffect18 } from "react";
8017
- import { Fragment as Fragment2, jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
8261
+ import { memo as memo10, useState as useState17, useCallback as useCallback15, useRef as useRef11, useEffect as useEffect19 } from "react";
8262
+ import { Fragment as Fragment2, jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
8018
8263
  var STRINGS = {
8019
8264
  en: {
8020
8265
  searchPlaceholder: "Search...",
@@ -8060,7 +8305,7 @@ var ResourcePicker = memo10(function ResourcePicker2({
8060
8305
  const scrollRestoredRef = useRef11(null);
8061
8306
  const [position, setPosition] = useState17({ top: 0, left: 0, width: 280 });
8062
8307
  const getScrollKey = (providerId) => `resource-picker-scroll-${providerId}`;
8063
- useEffect18(() => {
8308
+ useEffect19(() => {
8064
8309
  if (!isOpen || !anchorRef?.current) return;
8065
8310
  const updatePosition = () => {
8066
8311
  if (!anchorRef?.current) return;
@@ -8077,7 +8322,7 @@ var ResourcePicker = memo10(function ResourcePicker2({
8077
8322
  window.addEventListener("resize", updatePosition);
8078
8323
  return () => window.removeEventListener("resize", updatePosition);
8079
8324
  }, [isOpen, anchorRef]);
8080
- useEffect18(() => {
8325
+ useEffect19(() => {
8081
8326
  if (!isOpen) return;
8082
8327
  const handleClickOutside = (e) => {
8083
8328
  if (pickerRef.current && !pickerRef.current.contains(e.target)) {
@@ -8090,17 +8335,17 @@ var ResourcePicker = memo10(function ResourcePicker2({
8090
8335
  document.addEventListener("mousedown", handleClickOutside);
8091
8336
  return () => document.removeEventListener("mousedown", handleClickOutside);
8092
8337
  }, [isOpen, onClose, anchorRef]);
8093
- useEffect18(() => {
8338
+ useEffect19(() => {
8094
8339
  if (selectedProviderId && searchInputRef.current) {
8095
8340
  searchInputRef.current.focus();
8096
8341
  }
8097
8342
  }, [selectedProviderId]);
8098
- useEffect18(() => {
8343
+ useEffect19(() => {
8099
8344
  if (isOpen) {
8100
8345
  scrollRestoredRef.current = null;
8101
8346
  }
8102
8347
  }, [isOpen]);
8103
- useEffect18(() => {
8348
+ useEffect19(() => {
8104
8349
  if (!isOpen || !selectedProviderId || !listRef.current || resources.length === 0) return;
8105
8350
  if (scrollRestoredRef.current === selectedProviderId) return;
8106
8351
  const savedScroll = sessionStorage.getItem(getScrollKey(selectedProviderId));
@@ -8119,7 +8364,7 @@ var ResourcePicker = memo10(function ResourcePicker2({
8119
8364
  const scrollTop = e.currentTarget.scrollTop;
8120
8365
  sessionStorage.setItem(getScrollKey(selectedProviderId), String(scrollTop));
8121
8366
  }, [selectedProviderId]);
8122
- useEffect18(() => {
8367
+ useEffect19(() => {
8123
8368
  if (!isOpen) return;
8124
8369
  const handleKeyDown = (e) => {
8125
8370
  if (e.key === "Escape") {
@@ -8130,7 +8375,7 @@ var ResourcePicker = memo10(function ResourcePicker2({
8130
8375
  document.addEventListener("keydown", handleKeyDown);
8131
8376
  return () => document.removeEventListener("keydown", handleKeyDown);
8132
8377
  }, [isOpen, onClose]);
8133
- useEffect18(() => {
8378
+ useEffect19(() => {
8134
8379
  if (!sentinelRef.current || !hasMore || isLoadingResources) return;
8135
8380
  const observer = new IntersectionObserver(
8136
8381
  (entries) => {
@@ -8154,7 +8399,7 @@ var ResourcePicker = memo10(function ResourcePicker2({
8154
8399
  }, [onAttachResource]);
8155
8400
  if (!isOpen) return null;
8156
8401
  const showTabs = providers.length > 1;
8157
- return /* @__PURE__ */ jsxs9(
8402
+ return /* @__PURE__ */ jsxs8(
8158
8403
  "div",
8159
8404
  {
8160
8405
  ref: pickerRef,
@@ -8167,7 +8412,7 @@ var ResourcePicker = memo10(function ResourcePicker2({
8167
8412
  zIndex: 1e3
8168
8413
  },
8169
8414
  children: [
8170
- /* @__PURE__ */ jsxs9("div", { className: "resource-picker-content", children: [
8415
+ /* @__PURE__ */ jsxs8("div", { className: "resource-picker-content", children: [
8171
8416
  showTabs && /* @__PURE__ */ jsx14("div", { className: "resource-picker-tabs", children: providers.map((provider) => /* @__PURE__ */ jsx14(
8172
8417
  "button",
8173
8418
  {
@@ -8189,15 +8434,15 @@ var ResourcePicker = memo10(function ResourcePicker2({
8189
8434
  className: "resource-picker-search-input"
8190
8435
  }
8191
8436
  ) }),
8192
- /* @__PURE__ */ jsxs9("div", { ref: listRef, className: "resource-picker-list", onScroll: handleListScroll, children: [
8193
- error && /* @__PURE__ */ jsxs9("div", { className: "resource-picker-error", children: [
8437
+ /* @__PURE__ */ jsxs8("div", { ref: listRef, className: "resource-picker-list", onScroll: handleListScroll, children: [
8438
+ error && /* @__PURE__ */ jsxs8("div", { className: "resource-picker-error", children: [
8194
8439
  strings.error,
8195
8440
  error
8196
8441
  ] }),
8197
- isLoadingResources && resources.length === 0 ? /* @__PURE__ */ jsx14("div", { className: "resource-picker-loading", children: strings.loading }) : resources.length === 0 && !isLoadingResources ? /* @__PURE__ */ jsx14("div", { className: "resource-picker-empty", children: strings.noResults }) : /* @__PURE__ */ jsxs9(Fragment2, { children: [
8442
+ isLoadingResources && resources.length === 0 ? /* @__PURE__ */ jsx14("div", { className: "resource-picker-loading", children: strings.loading }) : resources.length === 0 && !isLoadingResources ? /* @__PURE__ */ jsx14("div", { className: "resource-picker-empty", children: strings.noResults }) : /* @__PURE__ */ jsxs8(Fragment2, { children: [
8198
8443
  resources.map((item) => {
8199
8444
  const attached = isResourceAttached?.(item.providerId, item.id);
8200
- return /* @__PURE__ */ jsxs9(
8445
+ return /* @__PURE__ */ jsxs8(
8201
8446
  "button",
8202
8447
  {
8203
8448
  className: `resource-picker-item ${attached ? "attached" : ""}`,
@@ -8205,7 +8450,7 @@ var ResourcePicker = memo10(function ResourcePicker2({
8205
8450
  disabled: attached,
8206
8451
  children: [
8207
8452
  item.icon && /* @__PURE__ */ jsx14("span", { className: "resource-picker-item-icon", children: item.icon }),
8208
- /* @__PURE__ */ jsxs9("div", { className: "resource-picker-item-content", children: [
8453
+ /* @__PURE__ */ jsxs8("div", { className: "resource-picker-item-content", children: [
8209
8454
  /* @__PURE__ */ jsx14("span", { className: "resource-picker-item-title", children: item.title }),
8210
8455
  item.summary && /* @__PURE__ */ jsx14("span", { className: "resource-picker-item-desc", children: item.summary })
8211
8456
  ] }),
@@ -8397,7 +8642,7 @@ var resourcePickerStyles = `
8397
8642
  `;
8398
8643
 
8399
8644
  // src/renderer/components/AddResourceButton.tsx
8400
- import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
8645
+ import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
8401
8646
  var STRINGS2 = {
8402
8647
  en: {
8403
8648
  addResource: "Add resource",
@@ -8435,7 +8680,7 @@ var AddResourceButton = memo11(function AddResourceButton2({
8435
8680
  const [isPickerOpen, setIsPickerOpen] = useState18(false);
8436
8681
  const buttonRef = useRef12(null);
8437
8682
  const menuRef = useRef12(null);
8438
- useEffect19(() => {
8683
+ useEffect20(() => {
8439
8684
  if (!isMenuOpen) return;
8440
8685
  const handleClickOutside = (e) => {
8441
8686
  if (menuRef.current && !menuRef.current.contains(e.target) && buttonRef.current && !buttonRef.current.contains(e.target)) {
@@ -8445,7 +8690,7 @@ var AddResourceButton = memo11(function AddResourceButton2({
8445
8690
  document.addEventListener("mousedown", handleClickOutside);
8446
8691
  return () => document.removeEventListener("mousedown", handleClickOutside);
8447
8692
  }, [isMenuOpen]);
8448
- useEffect19(() => {
8693
+ useEffect20(() => {
8449
8694
  if (!isMenuOpen) return;
8450
8695
  const handleKeyDown = (e) => {
8451
8696
  if (e.key === "Escape") {
@@ -8501,7 +8746,7 @@ var AddResourceButton = memo11(function AddResourceButton2({
8501
8746
  const hasUpload = onUploadFile || onUploadImage;
8502
8747
  const hasProviders = providers.length > 0;
8503
8748
  if (!hasUpload && !hasProviders) return null;
8504
- return /* @__PURE__ */ jsxs10("div", { className: "add-resource-container", children: [
8749
+ return /* @__PURE__ */ jsxs9("div", { className: "add-resource-container", children: [
8505
8750
  /* @__PURE__ */ jsx15(
8506
8751
  "button",
8507
8752
  {
@@ -8514,12 +8759,12 @@ var AddResourceButton = memo11(function AddResourceButton2({
8514
8759
  children: /* @__PURE__ */ jsx15("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx15("path", { d: "M12 5v14M5 12h14", strokeLinecap: "round" }) })
8515
8760
  }
8516
8761
  ),
8517
- isMenuOpen && /* @__PURE__ */ jsxs10("div", { ref: menuRef, className: "add-resource-menu", children: [
8518
- onUploadFile && /* @__PURE__ */ jsxs10("button", { className: "add-resource-menu-item", onClick: handleUploadFile, children: [
8762
+ isMenuOpen && /* @__PURE__ */ jsxs9("div", { ref: menuRef, className: "add-resource-menu", children: [
8763
+ onUploadFile && /* @__PURE__ */ jsxs9("button", { className: "add-resource-menu-item", onClick: handleUploadFile, children: [
8519
8764
  /* @__PURE__ */ jsx15("span", { className: "add-resource-menu-icon", children: "\u{1F4CE}" }),
8520
8765
  /* @__PURE__ */ jsx15("span", { children: strings.uploadFile })
8521
8766
  ] }),
8522
- onUploadImage && /* @__PURE__ */ jsxs10("button", { className: "add-resource-menu-item", onClick: handleUploadImage, children: [
8767
+ onUploadImage && /* @__PURE__ */ jsxs9("button", { className: "add-resource-menu-item", onClick: handleUploadImage, children: [
8523
8768
  /* @__PURE__ */ jsx15("span", { className: "add-resource-menu-icon", children: "\u{1F5BC}\uFE0F" }),
8524
8769
  /* @__PURE__ */ jsx15("span", { children: strings.uploadImage })
8525
8770
  ] }),
@@ -8648,15 +8893,15 @@ var addResourceButtonStyles = `
8648
8893
 
8649
8894
  // src/renderer/components/AttachedResourceTags.tsx
8650
8895
  import { memo as memo12 } from "react";
8651
- import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
8896
+ import { jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
8652
8897
  var AttachedResourceTags = memo12(function AttachedResourceTags2({
8653
8898
  resources,
8654
8899
  onRemove,
8655
8900
  disabled
8656
8901
  }) {
8657
8902
  if (resources.length === 0) return null;
8658
- return /* @__PURE__ */ jsxs11("div", { className: "attached-resource-tags", children: [
8659
- resources.map((resource) => /* @__PURE__ */ jsxs11("div", { className: "attached-resource-tag", children: [
8903
+ return /* @__PURE__ */ jsxs10("div", { className: "attached-resource-tags", children: [
8904
+ resources.map((resource) => /* @__PURE__ */ jsxs10("div", { className: "attached-resource-tag", children: [
8660
8905
  resource.icon && /* @__PURE__ */ jsx16("span", { className: "attached-resource-tag-icon", children: resource.icon }),
8661
8906
  /* @__PURE__ */ jsx16("span", { className: "attached-resource-tag-title", title: resource.summary, children: resource.title }),
8662
8907
  !disabled && /* @__PURE__ */ jsx16(
@@ -8727,7 +8972,7 @@ var attachedResourceTagsStyles = `
8727
8972
  `;
8728
8973
 
8729
8974
  // src/renderer/components/SanqianChat.tsx
8730
- import { Fragment as Fragment3, jsx as jsx17, jsxs as jsxs12 } from "react/jsx-runtime";
8975
+ import { Fragment as Fragment3, jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
8731
8976
  var SanqianChat = memo13(function SanqianChat2({
8732
8977
  adapter,
8733
8978
  placeholder,
@@ -8744,7 +8989,7 @@ var SanqianChat = memo13(function SanqianChat2({
8744
8989
  const chatInputRef = useRef13(null);
8745
8990
  const messageListRef = useRef13(null);
8746
8991
  const onStateChangeRef = useRef13(onStateChange);
8747
- useEffect20(() => {
8992
+ useEffect21(() => {
8748
8993
  onStateChangeRef.current = onStateChange;
8749
8994
  }, [onStateChange]);
8750
8995
  const resolvedConfig = useResolvedUiConfig(config);
@@ -8794,20 +9039,24 @@ var SanqianChat = memo13(function SanqianChat2({
8794
9039
  chat.submitHitlInput({ cancelled: true });
8795
9040
  }
8796
9041
  };
8797
- const handleSendMessage = useCallback17((content) => {
8798
- chat.sendMessage(content, {
8799
- attachedResources: resourcePicker.attachedResources.length > 0 ? resourcePicker.attachedResources : void 0
9042
+ const handleSendMessage = useCallback17(async (content) => {
9043
+ const attachedResources = resourcePicker.attachedResources.length > 0 ? [...resourcePicker.attachedResources] : void 0;
9044
+ const sent = await chat.trySendMessage(content, {
9045
+ attachedResources
8800
9046
  });
8801
- resourcePicker.clearAttachedResources();
9047
+ if (sent) {
9048
+ resourcePicker.clearAttachedResources();
9049
+ }
9050
+ return sent;
8802
9051
  }, [chat, resourcePicker]);
8803
- useEffect20(() => {
9052
+ useEffect21(() => {
8804
9053
  onStateChangeRef.current?.({
8805
9054
  messages: chat.messages,
8806
9055
  conversationId: chat.conversationId
8807
9056
  });
8808
9057
  }, [chat.messages, chat.conversationId]);
8809
9058
  const inputPlaceholder = placeholder ?? strings.inputPlaceholder;
8810
- return /* @__PURE__ */ jsxs12(
9059
+ return /* @__PURE__ */ jsxs11(
8811
9060
  "div",
8812
9061
  {
8813
9062
  ref: chatContainerRef,
@@ -8815,23 +9064,23 @@ var SanqianChat = memo13(function SanqianChat2({
8815
9064
  style: accentStyle,
8816
9065
  "data-chat-font-size": resolvedConfig?.fontSize || "normal",
8817
9066
  children: [
8818
- showHeader && /* @__PURE__ */ jsxs12("header", { className: "flex h-9 flex-shrink-0 items-center px-2 border-b chat-divider-border", children: [
8819
- /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2", children: [
9067
+ showHeader && /* @__PURE__ */ jsxs11("header", { className: "flex h-9 flex-shrink-0 items-center px-2 border-b chat-divider-border", children: [
9068
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2", children: [
8820
9069
  logoNode,
8821
9070
  /* @__PURE__ */ jsx17("span", { className: "text-sm font-medium text-[var(--chat-text)]", children: strings.chat })
8822
9071
  ] }),
8823
9072
  /* @__PURE__ */ jsx17("div", { className: "flex-1" }),
8824
- /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-1", children: [
9073
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-1", children: [
8825
9074
  showPin && /* @__PURE__ */ jsx17(
8826
9075
  "button",
8827
9076
  {
8828
9077
  onClick: togglePin,
8829
9078
  className: headerIconButtonClass,
8830
9079
  title: isPinned ? strings.unpin : strings.pin,
8831
- children: /* @__PURE__ */ jsx17("svg", { className: headerIconClass, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: isPinned ? /* @__PURE__ */ jsxs12(Fragment3, { children: [
9080
+ children: /* @__PURE__ */ jsx17("svg", { className: headerIconClass, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: isPinned ? /* @__PURE__ */ jsxs11(Fragment3, { children: [
8832
9081
  /* @__PURE__ */ jsx17("path", { d: "M12 17v5" }),
8833
9082
  /* @__PURE__ */ jsx17("path", { d: "M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H8a2 2 0 0 0 0 4 1 1 0 0 1 1 1z" })
8834
- ] }) : /* @__PURE__ */ jsxs12(Fragment3, { children: [
9083
+ ] }) : /* @__PURE__ */ jsxs11(Fragment3, { children: [
8835
9084
  /* @__PURE__ */ jsx17("path", { d: "M12 17v5" }),
8836
9085
  /* @__PURE__ */ jsx17("path", { d: "M15 9.34V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H7.89" }),
8837
9086
  /* @__PURE__ */ jsx17("path", { d: "m2 2 20 20" }),
@@ -8860,7 +9109,7 @@ var SanqianChat = memo13(function SanqianChat2({
8860
9109
  onClickEmpty: () => messageListRef.current?.scrollToBottom("auto")
8861
9110
  }
8862
9111
  ),
8863
- /* @__PURE__ */ jsxs12("div", { className: "px-4 pb-6 pt-4", children: [
9112
+ /* @__PURE__ */ jsxs11("div", { className: "px-4 pb-6 pt-4", children: [
8864
9113
  chat.error && /* @__PURE__ */ jsx17(
8865
9114
  AlertBanner,
8866
9115
  {
@@ -8916,6 +9165,7 @@ var SanqianChat = memo13(function SanqianChat2({
8916
9165
  stopLabel: strings.inputStop,
8917
9166
  isStreaming: chat.isStreaming,
8918
9167
  isLoading: chat.isLoading,
9168
+ allowEmptySubmit: resourcePicker.attachedResources.length > 0 || chat.sessionResources.length > 0,
8919
9169
  disabled: !!chat.pendingInterrupt || chat.isLoading && !chat.isStreaming,
8920
9170
  leftSlot: resourceProviders.length > 0 ? /* @__PURE__ */ jsx17(
8921
9171
  AddResourceButton,
@@ -8950,7 +9200,7 @@ import { memo as memo15, useCallback as useCallback19, useMemo as useMemo11, use
8950
9200
 
8951
9201
  // src/renderer/components/ModeToggleButton.tsx
8952
9202
  import { useMemo as useMemo9 } from "react";
8953
- import { jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
9203
+ import { jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
8954
9204
  function ModeToggleButton({ className, locale = "en" }) {
8955
9205
  const { isEmbedded, toggleMode } = useChatPanel();
8956
9206
  const strings = useMemo9(() => resolveChatStrings(locale), [locale]);
@@ -8958,7 +9208,7 @@ function ModeToggleButton({ className, locale = "en" }) {
8958
9208
  await toggleMode();
8959
9209
  };
8960
9210
  const tooltipText = isEmbedded ? strings.floatWindow : strings.embedWindow;
8961
- return /* @__PURE__ */ jsxs13("div", { className: `chat-tooltip-wrapper ${className || ""}`, children: [
9211
+ return /* @__PURE__ */ jsxs12("div", { className: `chat-tooltip-wrapper ${className || ""}`, children: [
8962
9212
  /* @__PURE__ */ jsx18(
8963
9213
  "button",
8964
9214
  {
@@ -8967,13 +9217,13 @@ function ModeToggleButton({ className, locale = "en" }) {
8967
9217
  "aria-label": tooltipText,
8968
9218
  children: isEmbedded ? (
8969
9219
  // Float out icon - two overlapping panels (macOS style)
8970
- /* @__PURE__ */ jsxs13("svg", { className: headerIconClass, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: [
9220
+ /* @__PURE__ */ jsxs12("svg", { className: headerIconClass, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: [
8971
9221
  /* @__PURE__ */ jsx18("rect", { x: "8", y: "3", width: "13", height: "13", rx: "2", strokeLinecap: "round", strokeLinejoin: "round" }),
8972
9222
  /* @__PURE__ */ jsx18("path", { d: "M5 8H4a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-1", strokeLinecap: "round", strokeLinejoin: "round" })
8973
9223
  ] })
8974
9224
  ) : (
8975
9225
  // Embed icon - panel with sidebar (dock to sidebar)
8976
- /* @__PURE__ */ jsxs13("svg", { className: headerIconClass, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: [
9226
+ /* @__PURE__ */ jsxs12("svg", { className: headerIconClass, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: [
8977
9227
  /* @__PURE__ */ jsx18("rect", { x: "3", y: "4", width: "18", height: "16", rx: "2", strokeLinecap: "round", strokeLinejoin: "round" }),
8978
9228
  /* @__PURE__ */ jsx18("path", { d: "M15 4v16", strokeLinecap: "round" })
8979
9229
  ] })
@@ -8986,7 +9236,7 @@ function ModeToggleButton({ className, locale = "en" }) {
8986
9236
 
8987
9237
  // src/renderer/components/AttachButton.tsx
8988
9238
  import { useMemo as useMemo10 } from "react";
8989
- import { jsx as jsx19, jsxs as jsxs14 } from "react/jsx-runtime";
9239
+ import { jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
8990
9240
  function AttachButton({ className, locale = "en" }) {
8991
9241
  const { isAttached, isAvailable, toggle } = useAttachState();
8992
9242
  const { isFloating } = useChatPanel();
@@ -8996,7 +9246,7 @@ function AttachButton({ className, locale = "en" }) {
8996
9246
  await toggle();
8997
9247
  };
8998
9248
  const tooltipText = isAttached ? strings.detachWindow : strings.attachWindow;
8999
- return /* @__PURE__ */ jsxs14("div", { className: `chat-tooltip-wrapper ${className || ""}`, children: [
9249
+ return /* @__PURE__ */ jsxs13("div", { className: `chat-tooltip-wrapper ${className || ""}`, children: [
9000
9250
  /* @__PURE__ */ jsx19(
9001
9251
  "button",
9002
9252
  {
@@ -9005,13 +9255,13 @@ function AttachButton({ className, locale = "en" }) {
9005
9255
  "aria-label": tooltipText,
9006
9256
  children: isAttached ? (
9007
9257
  // Attached state: filled icon
9008
- /* @__PURE__ */ jsxs14("svg", { className: headerIconClass, viewBox: "0 0 16 16", fill: "currentColor", children: [
9258
+ /* @__PURE__ */ jsxs13("svg", { className: headerIconClass, viewBox: "0 0 16 16", fill: "currentColor", children: [
9009
9259
  /* @__PURE__ */ jsx19("path", { d: "M4.5 2A2.5 2.5 0 0 0 2 4.5v7A2.5 2.5 0 0 0 4.5 14h7a2.5 2.5 0 0 0 2.5-2.5v-7A2.5 2.5 0 0 0 11.5 2h-7z" }),
9010
9260
  /* @__PURE__ */ jsx19("path", { d: "M9.5 6.5h3v1h-3v-1z", fill: "var(--bg-color, #fff)" })
9011
9261
  ] })
9012
9262
  ) : (
9013
9263
  // Detached state: outline icon
9014
- /* @__PURE__ */ jsxs14("svg", { className: headerIconClass, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: [
9264
+ /* @__PURE__ */ jsxs13("svg", { className: headerIconClass, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: [
9015
9265
  /* @__PURE__ */ jsx19("rect", { x: "2.5", y: "2.5", width: "11", height: "11", rx: "2" }),
9016
9266
  /* @__PURE__ */ jsx19("path", { d: "M9.5 6.5h3", strokeLinecap: "round" })
9017
9267
  ] })
@@ -9023,8 +9273,8 @@ function AttachButton({ className, locale = "en" }) {
9023
9273
  }
9024
9274
 
9025
9275
  // src/renderer/components/Resizer.tsx
9026
- import { useCallback as useCallback18, useRef as useRef14, useEffect as useEffect21, useLayoutEffect, useState as useState19 } from "react";
9027
- import { jsx as jsx20, jsxs as jsxs15 } from "react/jsx-runtime";
9276
+ import { useCallback as useCallback18, useRef as useRef14, useEffect as useEffect22, useLayoutEffect, useState as useState19 } from "react";
9277
+ import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
9028
9278
  function useRafThrottle(fn) {
9029
9279
  const rafRef = useRef14(null);
9030
9280
  const argsRef = useRef14(null);
@@ -9043,7 +9293,7 @@ function useRafThrottle(fn) {
9043
9293
  });
9044
9294
  }
9045
9295
  }, []);
9046
- useEffect21(() => {
9296
+ useEffect22(() => {
9047
9297
  return () => {
9048
9298
  if (rafRef.current !== null) {
9049
9299
  cancelAnimationFrame(rafRef.current);
@@ -9081,7 +9331,7 @@ function Resizer({
9081
9331
  document.body.style.cursor = "col-resize";
9082
9332
  document.body.style.userSelect = "none";
9083
9333
  }, []);
9084
- useEffect21(() => {
9334
+ useEffect22(() => {
9085
9335
  if (!isDragging) return;
9086
9336
  const handleMouseMove = (e) => {
9087
9337
  const deltaX = e.screenX - startX.current;
@@ -9104,7 +9354,7 @@ function Resizer({
9104
9354
  }, [isDragging, position, minWidth, maxWidth, throttledSetWidth, onResizeEnd]);
9105
9355
  if (!isEmbedded) return null;
9106
9356
  const isActive = isHovered || isDragging;
9107
- return /* @__PURE__ */ jsxs15(
9357
+ return /* @__PURE__ */ jsxs14(
9108
9358
  "div",
9109
9359
  {
9110
9360
  className: `chat-resizer${className ? ` ${className}` : ""}`,
@@ -9159,7 +9409,7 @@ function Resizer({
9159
9409
 
9160
9410
  // src/renderer/components/ResourceChip.tsx
9161
9411
  import { memo as memo14, useContext as useContext3 } from "react";
9162
- import { jsx as jsx21, jsxs as jsxs16 } from "react/jsx-runtime";
9412
+ import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
9163
9413
  var ResourceChip = memo14(function ResourceChip2({
9164
9414
  resource,
9165
9415
  onRemove,
@@ -9169,7 +9419,7 @@ var ResourceChip = memo14(function ResourceChip2({
9169
9419
  const i18nContext = useContext3(I18nContext);
9170
9420
  const locale = i18nContext?.locale ?? localeProp ?? "en";
9171
9421
  const strings = resolveChatStrings(locale);
9172
- return /* @__PURE__ */ jsxs16("div", { className: `resource-chip ${disabled ? "disabled" : ""}`, children: [
9422
+ return /* @__PURE__ */ jsxs15("div", { className: `resource-chip ${disabled ? "disabled" : ""}`, children: [
9173
9423
  resource.icon && /* @__PURE__ */ jsx21("span", { className: "resource-chip-icon", children: resource.icon }),
9174
9424
  /* @__PURE__ */ jsx21("span", { className: "resource-chip-title", title: resource.summary || resource.title, children: resource.title }),
9175
9425
  /* @__PURE__ */ jsx21(
@@ -9264,7 +9514,7 @@ var resourceChipStyles = `
9264
9514
  `;
9265
9515
 
9266
9516
  // src/renderer/hooks/useWindowBackgroundSync.ts
9267
- import { useEffect as useEffect22 } from "react";
9517
+ import { useEffect as useEffect23 } from "react";
9268
9518
  var cachedPlatform = null;
9269
9519
  var getPlatform = () => {
9270
9520
  if (cachedPlatform !== null) return cachedPlatform;
@@ -9282,7 +9532,7 @@ var setBackgroundColor = (color) => {
9282
9532
  }
9283
9533
  };
9284
9534
  function useWindowBackgroundSync(isDarkMode) {
9285
- useEffect22(() => {
9535
+ useEffect23(() => {
9286
9536
  if (getPlatform() !== "win32") return;
9287
9537
  const colors = getBaseColors(isDarkMode);
9288
9538
  setBackgroundColor(colors.bg);
@@ -9290,7 +9540,7 @@ function useWindowBackgroundSync(isDarkMode) {
9290
9540
  }
9291
9541
 
9292
9542
  // src/renderer/components/FloatingChat.tsx
9293
- import { Fragment as Fragment4, jsx as jsx22, jsxs as jsxs17 } from "react/jsx-runtime";
9543
+ import { Fragment as Fragment4, jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
9294
9544
  var FloatingChat = memo15(function FloatingChat2({
9295
9545
  messages,
9296
9546
  isLoading,
@@ -9354,25 +9604,25 @@ var FloatingChat = memo15(function FloatingChat2({
9354
9604
  const emptyLogoNode = useMemo11(() => resolveLogoNode(resolvedLogo, "empty"), [resolvedLogo]);
9355
9605
  const inputPlaceholder = placeholder ?? resolvedStrings.inputPlaceholder;
9356
9606
  const showHeader = !!(header || logoNode || showPin || showClose);
9357
- const defaultHeader = /* @__PURE__ */ jsxs17("header", { className: "flex h-9 flex-shrink-0 items-center px-2 border-b chat-divider-border", children: [
9358
- /* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-2", children: [
9607
+ const defaultHeader = /* @__PURE__ */ jsxs16("header", { className: "flex h-9 flex-shrink-0 items-center px-2 border-b chat-divider-border", children: [
9608
+ /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-2", children: [
9359
9609
  logoNode,
9360
9610
  /* @__PURE__ */ jsx22("span", { className: "text-sm font-medium text-[var(--chat-text)]", children: resolvedStrings.chat })
9361
9611
  ] }),
9362
9612
  /* @__PURE__ */ jsx22("div", { className: "flex-1" }),
9363
- /* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-1", children: [
9613
+ /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-1", children: [
9364
9614
  /* @__PURE__ */ jsx22(ModeToggleButton, { locale: resolvedLocale }),
9365
9615
  /* @__PURE__ */ jsx22(AttachButton, { locale: resolvedLocale }),
9366
- showPin && /* @__PURE__ */ jsxs17("div", { className: "chat-tooltip-wrapper", children: [
9616
+ showPin && /* @__PURE__ */ jsxs16("div", { className: "chat-tooltip-wrapper", children: [
9367
9617
  /* @__PURE__ */ jsx22(
9368
9618
  "button",
9369
9619
  {
9370
9620
  onClick: togglePin,
9371
9621
  className: headerIconButtonClass,
9372
- children: /* @__PURE__ */ jsx22("svg", { className: headerIconClass, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: isPinned ? /* @__PURE__ */ jsxs17(Fragment4, { children: [
9622
+ children: /* @__PURE__ */ jsx22("svg", { className: headerIconClass, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: isPinned ? /* @__PURE__ */ jsxs16(Fragment4, { children: [
9373
9623
  /* @__PURE__ */ jsx22("path", { d: "M12 17v5" }),
9374
9624
  /* @__PURE__ */ jsx22("path", { d: "M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H8a2 2 0 0 0 0 4 1 1 0 0 1 1 1z" })
9375
- ] }) : /* @__PURE__ */ jsxs17(Fragment4, { children: [
9625
+ ] }) : /* @__PURE__ */ jsxs16(Fragment4, { children: [
9376
9626
  /* @__PURE__ */ jsx22("path", { d: "M12 17v5" }),
9377
9627
  /* @__PURE__ */ jsx22("path", { d: "M15 9.34V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H7.89" }),
9378
9628
  /* @__PURE__ */ jsx22("path", { d: "m2 2 20 20" }),
@@ -9382,7 +9632,7 @@ var FloatingChat = memo15(function FloatingChat2({
9382
9632
  ),
9383
9633
  /* @__PURE__ */ jsx22("div", { className: "chat-tooltip", children: isPinned ? resolvedStrings.unpin : resolvedStrings.pin })
9384
9634
  ] }),
9385
- showClose && /* @__PURE__ */ jsxs17("div", { className: "chat-tooltip-wrapper", children: [
9635
+ showClose && /* @__PURE__ */ jsxs16("div", { className: "chat-tooltip-wrapper", children: [
9386
9636
  /* @__PURE__ */ jsx22(
9387
9637
  "button",
9388
9638
  {
@@ -9411,16 +9661,16 @@ var FloatingChat = memo15(function FloatingChat2({
9411
9661
  [renderContent]
9412
9662
  );
9413
9663
  const defaultRenderHitl = useCallback19(
9414
- (interrupt, onApprove, onReject) => /* @__PURE__ */ jsxs17("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: [
9664
+ (interrupt, onApprove, onReject) => /* @__PURE__ */ jsxs16("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: [
9415
9665
  /* @__PURE__ */ jsx22("p", { className: "font-medium mb-2", children: interrupt.type === "approval_request" ? resolvedStrings.hitlApprovalRequired : resolvedStrings.hitlInputRequired }),
9416
- interrupt.tool && /* @__PURE__ */ jsxs17("p", { className: "text-sm mb-2", children: [
9666
+ interrupt.tool && /* @__PURE__ */ jsxs16("p", { className: "text-sm mb-2", children: [
9417
9667
  resolvedStrings.hitlToolLabel,
9418
9668
  ": ",
9419
9669
  interrupt.tool
9420
9670
  ] }),
9421
9671
  interrupt.reason && /* @__PURE__ */ jsx22("p", { className: "text-sm mb-2", children: interrupt.reason }),
9422
9672
  interrupt.question && /* @__PURE__ */ jsx22("p", { className: "text-sm mb-2", children: interrupt.question }),
9423
- /* @__PURE__ */ jsxs17("div", { className: "flex gap-2 mt-3", children: [
9673
+ /* @__PURE__ */ jsxs16("div", { className: "flex gap-2 mt-3", children: [
9424
9674
  /* @__PURE__ */ jsx22(
9425
9675
  "button",
9426
9676
  {
@@ -9441,7 +9691,7 @@ var FloatingChat = memo15(function FloatingChat2({
9441
9691
  ] }),
9442
9692
  [resolvedStrings]
9443
9693
  );
9444
- return /* @__PURE__ */ jsxs17("div", { ref: chatContainerRef, className: `relative flex flex-col h-full bg-[var(--chat-bg)] text-[var(--chat-text)] ${themeClass}${className ? ` ${className}` : ""}`, style: rootStyle, "data-chat-font-size": resolvedConfig?.fontSize || "normal", children: [
9694
+ return /* @__PURE__ */ jsxs16("div", { ref: chatContainerRef, className: `relative flex flex-col h-full bg-[var(--chat-bg)] text-[var(--chat-text)] ${themeClass}${className ? ` ${className}` : ""}`, style: rootStyle, "data-chat-font-size": resolvedConfig?.fontSize || "normal", children: [
9445
9695
  /* @__PURE__ */ jsx22(Resizer, { position: "left", minWidth: 240, maxWidth: 600 }),
9446
9696
  resolvedHeader && /* @__PURE__ */ jsx22("div", { className: "flex-shrink-0", children: resolvedHeader }),
9447
9697
  messages.length === 0 ? /* @__PURE__ */ jsx22("div", { className: "flex flex-1 items-center justify-center p-4", children: /* @__PURE__ */ jsx22("div", { className: "flex items-center justify-center", children: emptyLogoNode }) }) : /* @__PURE__ */ jsx22(
@@ -9491,6 +9741,7 @@ var FloatingChat = memo15(function FloatingChat2({
9491
9741
  stopLabel: resolvedStrings.inputStop,
9492
9742
  isStreaming,
9493
9743
  isLoading,
9744
+ allowEmptySubmit: !!sessionResources && sessionResources.length > 0,
9494
9745
  disabled: !!pendingInterrupt || isLoading && !isStreaming,
9495
9746
  autoFocus: true
9496
9747
  }
@@ -9500,8 +9751,8 @@ var FloatingChat = memo15(function FloatingChat2({
9500
9751
  });
9501
9752
 
9502
9753
  // src/renderer/components/HistoryList.tsx
9503
- import { memo as memo16, useState as useState20, useEffect as useEffect23, useRef as useRef16 } from "react";
9504
- import { jsx as jsx23, jsxs as jsxs18 } from "react/jsx-runtime";
9754
+ import { memo as memo16, useState as useState20, useEffect as useEffect24, useRef as useRef16 } from "react";
9755
+ import { jsx as jsx23, jsxs as jsxs17 } from "react/jsx-runtime";
9505
9756
  function DeleteButton({ onClick, title, colors }) {
9506
9757
  const [isHovered, setIsHovered] = useState20(false);
9507
9758
  return /* @__PURE__ */ jsx23(
@@ -9612,10 +9863,10 @@ var HistoryList = memo16(function HistoryList2({
9612
9863
  const [hoveredId, setHoveredId] = useState20(null);
9613
9864
  const loadMoreRef = useRef16(null);
9614
9865
  const isLoadingRef = useRef16(isLoading);
9615
- useEffect23(() => {
9866
+ useEffect24(() => {
9616
9867
  isLoadingRef.current = isLoading;
9617
9868
  }, [isLoading]);
9618
- useEffect23(() => {
9869
+ useEffect24(() => {
9619
9870
  if (!hasMore || loadError || !onLoadMore) return;
9620
9871
  const sentinel = loadMoreRef.current;
9621
9872
  if (!sentinel) return;
@@ -9659,11 +9910,11 @@ var HistoryList = memo16(function HistoryList2({
9659
9910
  if (conversations.length === 0) {
9660
9911
  return /* @__PURE__ */ jsx23("div", { style: { textAlign: "center", color: colors.muted, padding: "1.5rem 0", fontSize: "0.875rem" }, children: strings.noHistory || "No conversations yet" });
9661
9912
  }
9662
- return /* @__PURE__ */ jsxs18("div", { style: { padding: "0.25rem 0.75rem 0" }, children: [
9913
+ return /* @__PURE__ */ jsxs17("div", { style: { padding: "0.25rem 0.75rem 0" }, children: [
9663
9914
  conversations.map((conv) => {
9664
9915
  const isSelected = conv.id === selectedId;
9665
9916
  const isHovered = conv.id === hoveredId;
9666
- return /* @__PURE__ */ jsxs18(
9917
+ return /* @__PURE__ */ jsxs17(
9667
9918
  "div",
9668
9919
  {
9669
9920
  style: {
@@ -9681,7 +9932,7 @@ var HistoryList = memo16(function HistoryList2({
9681
9932
  onMouseEnter: () => setHoveredId(conv.id),
9682
9933
  onMouseLeave: () => setHoveredId(null),
9683
9934
  children: [
9684
- /* @__PURE__ */ jsxs18("div", { style: { minWidth: 0, flex: 1 }, children: [
9935
+ /* @__PURE__ */ jsxs17("div", { style: { minWidth: 0, flex: 1 }, children: [
9685
9936
  /* @__PURE__ */ jsx23("div", { style: {
9686
9937
  fontSize: "0.875rem",
9687
9938
  color: colors.text,
@@ -9712,8 +9963,8 @@ var HistoryList = memo16(function HistoryList2({
9712
9963
  });
9713
9964
 
9714
9965
  // src/renderer/components/HistoryModal.tsx
9715
- import { memo as memo17, useEffect as useEffect24, useCallback as useCallback20, useRef as useRef17, useState as useState21 } from "react";
9716
- import { jsx as jsx24, jsxs as jsxs19 } from "react/jsx-runtime";
9966
+ import { memo as memo17, useEffect as useEffect25, useCallback as useCallback20, useRef as useRef17, useState as useState21 } from "react";
9967
+ import { jsx as jsx24, jsxs as jsxs18 } from "react/jsx-runtime";
9717
9968
  var ANIMATION_DURATION = 120;
9718
9969
  var HistoryModal = memo17(function HistoryModal2({
9719
9970
  isOpen,
@@ -9726,7 +9977,7 @@ var HistoryModal = memo17(function HistoryModal2({
9726
9977
  const modalRef = useRef17(null);
9727
9978
  const [isClosing, setIsClosing] = useState21(false);
9728
9979
  const [shouldRender, setShouldRender] = useState21(isOpen);
9729
- useEffect24(() => {
9980
+ useEffect25(() => {
9730
9981
  if (isOpen) {
9731
9982
  setShouldRender(true);
9732
9983
  setIsClosing(false);
@@ -9746,7 +9997,7 @@ var HistoryModal = memo17(function HistoryModal2({
9746
9997
  onClose();
9747
9998
  }, ANIMATION_DURATION);
9748
9999
  }, [onClose]);
9749
- useEffect24(() => {
10000
+ useEffect25(() => {
9750
10001
  if (!shouldRender || isClosing) return;
9751
10002
  const handleKeyDown = (e) => {
9752
10003
  if (e.key === "Escape") {
@@ -9757,7 +10008,7 @@ var HistoryModal = memo17(function HistoryModal2({
9757
10008
  document.addEventListener("keydown", handleKeyDown);
9758
10009
  return () => document.removeEventListener("keydown", handleKeyDown);
9759
10010
  }, [shouldRender, isClosing, handleClose]);
9760
- useEffect24(() => {
10011
+ useEffect25(() => {
9761
10012
  if (!isOpen || !modalRef.current) return;
9762
10013
  modalRef.current.focus();
9763
10014
  }, [isOpen]);
@@ -9785,7 +10036,7 @@ var HistoryModal = memo17(function HistoryModal2({
9785
10036
  background: "rgba(0, 0, 0, 0.5)"
9786
10037
  },
9787
10038
  onClick: handleBackdropClick,
9788
- children: /* @__PURE__ */ jsxs19(
10039
+ children: /* @__PURE__ */ jsxs18(
9789
10040
  "div",
9790
10041
  {
9791
10042
  ref: modalRef,
@@ -9810,7 +10061,7 @@ var HistoryModal = memo17(function HistoryModal2({
9810
10061
  },
9811
10062
  onClick: (e) => e.stopPropagation(),
9812
10063
  children: [
9813
- /* @__PURE__ */ jsxs19(
10064
+ /* @__PURE__ */ jsxs18(
9814
10065
  "div",
9815
10066
  {
9816
10067
  style: {
@@ -9900,17 +10151,17 @@ var HistoryModal = memo17(function HistoryModal2({
9900
10151
  });
9901
10152
 
9902
10153
  // src/renderer/components/CompactChat.tsx
9903
- import { memo as memo18, useRef as useRef18, useState as useState22, useEffect as useEffect25, useCallback as useCallback21, useMemo as useMemo12 } from "react";
10154
+ import { memo as memo18, useRef as useRef18, useState as useState22, useEffect as useEffect26, useCallback as useCallback21, useMemo as useMemo12 } from "react";
9904
10155
  import { createPortal } from "react-dom";
9905
10156
 
9906
10157
  // src/renderer/components/PanelControls.tsx
9907
- import { Fragment as Fragment5, jsx as jsx25, jsxs as jsxs20 } from "react/jsx-runtime";
10158
+ import { Fragment as Fragment5, jsx as jsx25, jsxs as jsxs19 } from "react/jsx-runtime";
9908
10159
  function PanelHeaderButtons({
9909
10160
  showModeToggle = true,
9910
10161
  showAttachToggle = true,
9911
10162
  locale = "en"
9912
10163
  }) {
9913
- return /* @__PURE__ */ jsxs20(Fragment5, { children: [
10164
+ return /* @__PURE__ */ jsxs19(Fragment5, { children: [
9914
10165
  showModeToggle && /* @__PURE__ */ jsx25(ModeToggleButton, { locale }),
9915
10166
  showAttachToggle && /* @__PURE__ */ jsx25(AttachButton, { locale })
9916
10167
  ] });
@@ -9939,7 +10190,7 @@ var PanelControls = {
9939
10190
  };
9940
10191
 
9941
10192
  // src/renderer/components/CompactChat.tsx
9942
- import { Fragment as Fragment6, jsx as jsx26, jsxs as jsxs21 } from "react/jsx-runtime";
10193
+ import { Fragment as Fragment6, jsx as jsx26, jsxs as jsxs20 } from "react/jsx-runtime";
9943
10194
  var CompactChat = memo18(function CompactChat2({
9944
10195
  adapter,
9945
10196
  config,
@@ -9999,6 +10250,7 @@ var CompactChat = memo18(function CompactChat2({
9999
10250
  const chatContainerRef = useRef18(null);
10000
10251
  const chatInputRef = useRef18(null);
10001
10252
  const [showHistory, setShowHistory] = useState22(false);
10253
+ useWindowDragLock(showHistory);
10002
10254
  const [connectionAlert, setConnectionAlert] = useState22(null);
10003
10255
  const portalContainerRef = useRef18(inputPortalContainer ?? null);
10004
10256
  portalContainerRef.current = inputPortalContainer ?? null;
@@ -10050,38 +10302,44 @@ var CompactChat = memo18(function CompactChat2({
10050
10302
  chat.submitHitlInput({ cancelled: true });
10051
10303
  }
10052
10304
  }, [chat.pendingInterrupt?.type, chat.rejectHitl, chat.submitHitlInput]);
10053
- const handleSendWithResources = useCallback21((content) => {
10054
- const resources = resourcePicker.attachedResources;
10055
- chat.sendMessage(content, resources.length > 0 ? { attachedResources: resources } : void 0);
10056
- resourcePicker.clearAttachedResources();
10057
- }, [chat.sendMessage, resourcePicker.attachedResources, resourcePicker.clearAttachedResources]);
10058
- useEffect25(() => {
10305
+ const handleSendWithResources = useCallback21(async (content) => {
10306
+ const resources = [...resourcePicker.attachedResources];
10307
+ const sent = await chat.trySendMessage(
10308
+ content,
10309
+ resources.length > 0 ? { attachedResources: resources } : void 0
10310
+ );
10311
+ if (sent) {
10312
+ resourcePicker.clearAttachedResources();
10313
+ }
10314
+ return sent;
10315
+ }, [chat.trySendMessage, resourcePicker.attachedResources, resourcePicker.clearAttachedResources]);
10316
+ useEffect26(() => {
10059
10317
  if (sendMessageRef) {
10060
10318
  sendMessageRef.current = chat.sendMessage;
10061
10319
  }
10062
10320
  }, [sendMessageRef, chat.sendMessage]);
10063
- useEffect25(() => {
10321
+ useEffect26(() => {
10064
10322
  if (newConversationRef) {
10065
10323
  newConversationRef.current = chat.newConversation;
10066
10324
  }
10067
10325
  }, [newConversationRef, chat.newConversation]);
10068
- useEffect25(() => {
10326
+ useEffect26(() => {
10069
10327
  if (parentFocusInputRef) {
10070
10328
  parentFocusInputRef.current = () => chatInputRef.current?.focus();
10071
10329
  }
10072
10330
  }, [parentFocusInputRef]);
10073
- useEffect25(() => {
10331
+ useEffect26(() => {
10074
10332
  if (parentSetTextRef) {
10075
10333
  parentSetTextRef.current = (text) => chatInputRef.current?.setValue(text);
10076
10334
  }
10077
10335
  }, [parentSetTextRef]);
10078
- useEffect25(() => {
10336
+ useEffect26(() => {
10079
10337
  if (!adapter.onFocusInput) return;
10080
10338
  return adapter.onFocusInput(() => {
10081
10339
  chatInputRef.current?.focus();
10082
10340
  });
10083
10341
  }, [adapter]);
10084
- useEffect25(() => {
10342
+ useEffect26(() => {
10085
10343
  if (onMessageReceived && chat.messages.length > 0) {
10086
10344
  const lastMessage = chat.messages[chat.messages.length - 1];
10087
10345
  if (lastMessage.role === "assistant" && !lastMessage.isStreaming) {
@@ -10089,12 +10347,12 @@ var CompactChat = memo18(function CompactChat2({
10089
10347
  }
10090
10348
  }
10091
10349
  }, [chat.messages, onMessageReceived]);
10092
- useEffect25(() => {
10350
+ useEffect26(() => {
10093
10351
  if (onLoadingChange) {
10094
10352
  onLoadingChange(chat.isLoading);
10095
10353
  }
10096
10354
  }, [chat.isLoading, onLoadingChange]);
10097
- useEffect25(() => {
10355
+ useEffect26(() => {
10098
10356
  if (onStateChange) {
10099
10357
  onStateChange({
10100
10358
  messages: chat.messages,
@@ -10102,12 +10360,12 @@ var CompactChat = memo18(function CompactChat2({
10102
10360
  });
10103
10361
  }
10104
10362
  }, [chat.messages, chat.conversationId, onStateChange]);
10105
- useEffect25(() => {
10363
+ useEffect26(() => {
10106
10364
  if (connection.isConnected) {
10107
10365
  resourcePicker.refreshProviders();
10108
10366
  }
10109
10367
  }, [connection.isConnected]);
10110
- useEffect25(() => {
10368
+ useEffect26(() => {
10111
10369
  if (showHistory && connection.isConnected) {
10112
10370
  conversations.loadConversations();
10113
10371
  }
@@ -10135,7 +10393,7 @@ var CompactChat = memo18(function CompactChat2({
10135
10393
  chatInputRef.current?.focus();
10136
10394
  }, 0);
10137
10395
  }, [chat]);
10138
- useEffect25(() => {
10396
+ useEffect26(() => {
10139
10397
  const handleKeyDown = (e) => {
10140
10398
  const isMac2 = navigator.platform.includes("Mac");
10141
10399
  const modifierKey = isMac2 ? e.metaKey : e.ctrlKey;
@@ -10152,17 +10410,16 @@ var CompactChat = memo18(function CompactChat2({
10152
10410
  const defaultRenderMessage = useCallback21((message) => {
10153
10411
  if (message.role === "tool") return null;
10154
10412
  const isUser = message.role === "user";
10155
- const hasToolCalls = message.toolCalls && message.toolCalls.length > 0;
10156
- const hasToolBlocks = message.blocks && message.blocks.some((b) => b.type === "tool_call" || b.type === "tool_result");
10157
- const hasToolActivity = Boolean(hasToolCalls || hasToolBlocks);
10158
- const hasIntermediateBlocks = message.blocks && message.blocks.some((b) => b.isIntermediate);
10159
- const showIntermediateSteps = message.isComplete && hasIntermediateBlocks && hasToolActivity;
10160
- const showStreamingTimeline = !isUser && !showIntermediateSteps && hasToolActivity;
10161
- const hasThinking = message.thinking || message.isThinkingStreaming || message.currentThinking;
10162
- const showThinkingSection = !isUser && !hasToolActivity && !showIntermediateSteps && hasThinking;
10163
- const isToolCallsStreaming = message.isToolCallsStreaming ?? ((message.toolCalls?.some((tc) => tc.status === "running") ?? false) || (message.blocks?.some((b) => b.type === "tool_call" && b.toolStatus === "running") ?? false));
10164
- return /* @__PURE__ */ jsx26("div", { className: `flex ${isUser ? "justify-end" : "justify-start"} mb-4`, children: /* @__PURE__ */ jsxs21("div", { className: `text-left ${isUser ? "max-w-[80%]" : "w-full"}`, children: [
10165
- !isUser && showIntermediateSteps && message.blocks && /* @__PURE__ */ jsx26(IntermediateSteps, { blocks: message.blocks, strings: mergedStrings }),
10413
+ const {
10414
+ displayBlocks,
10415
+ isEffectivelyComplete,
10416
+ showIntermediateSteps,
10417
+ showStreamingTimeline,
10418
+ showThinkingSection
10419
+ } = getAssistantDisplayState(message);
10420
+ const isToolCallsStreaming = message.isToolCallsStreaming ?? ((message.toolCalls?.some((tc) => tc.status === "running") ?? false) || (displayBlocks?.some((b) => b.type === "tool_call" && b.toolStatus === "running") ?? false));
10421
+ return /* @__PURE__ */ jsx26("div", { className: `flex ${isUser ? "justify-end" : "justify-start"} mb-4`, children: /* @__PURE__ */ jsxs20("div", { className: `text-left ${isUser ? "max-w-[80%]" : "w-full"}`, children: [
10422
+ !isUser && showIntermediateSteps && displayBlocks && /* @__PURE__ */ jsx26(IntermediateSteps, { blocks: displayBlocks, strings: mergedStrings }),
10166
10423
  showThinkingSection && /* @__PURE__ */ jsx26(
10167
10424
  ThinkingSection,
10168
10425
  {
@@ -10170,18 +10427,18 @@ var CompactChat = memo18(function CompactChat2({
10170
10427
  currentThinking: message.currentThinking,
10171
10428
  isStreaming: message.isThinkingStreaming,
10172
10429
  isPaused: message.isThinkingPaused,
10173
- isComplete: message.isComplete,
10430
+ isComplete: isEffectivelyComplete,
10174
10431
  strings: mergedStrings
10175
10432
  }
10176
10433
  ),
10177
- showStreamingTimeline && message.blocks && /* @__PURE__ */ jsx26(
10434
+ showStreamingTimeline && displayBlocks && /* @__PURE__ */ jsx26(
10178
10435
  StreamingTimeline,
10179
10436
  {
10180
- blocks: message.blocks,
10437
+ blocks: displayBlocks,
10181
10438
  currentThinking: message.currentThinking,
10182
10439
  isThinkingStreaming: message.isThinkingStreaming,
10183
10440
  isToolCallsStreaming,
10184
- isComplete: message.isComplete,
10441
+ isComplete: isEffectivelyComplete,
10185
10442
  strings: mergedStrings
10186
10443
  }
10187
10444
  ),
@@ -10226,7 +10483,7 @@ var CompactChat = memo18(function CompactChat2({
10226
10483
  }
10227
10484
  return baseStyle;
10228
10485
  }, [floating, baseColors, accentStyle, resolvedIsDarkMode, isEmbedded]);
10229
- return /* @__PURE__ */ jsxs21(
10486
+ return /* @__PURE__ */ jsxs20(
10230
10487
  "div",
10231
10488
  {
10232
10489
  ref: chatContainerRef,
@@ -10235,16 +10492,16 @@ var CompactChat = memo18(function CompactChat2({
10235
10492
  "data-chat-font-size": resolvedConfig?.fontSize || "normal",
10236
10493
  children: [
10237
10494
  /* @__PURE__ */ jsx26(PanelResizer, {}),
10238
- !hideHeader && /* @__PURE__ */ jsx26("header", { className: "flex flex-shrink-0 items-center px-2 border-b chat-divider-border", style: { height: 42, WebkitAppRegion: "drag" }, children: isEmbedded ? (
10495
+ !hideHeader && /* @__PURE__ */ jsx26("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 ? (
10239
10496
  // Embedded mode: left-aligned buttons (collapse, float, history, new chat)
10240
- /* @__PURE__ */ jsxs21("div", { className: "flex items-center gap-0.5", style: { WebkitAppRegion: "no-drag" }, children: [
10241
- /* @__PURE__ */ jsxs21("div", { className: "chat-tooltip-wrapper", children: [
10497
+ /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-0.5", style: { WebkitAppRegion: "no-drag" }, children: [
10498
+ /* @__PURE__ */ jsxs20("div", { className: "chat-tooltip-wrapper", children: [
10242
10499
  /* @__PURE__ */ jsx26(
10243
10500
  "button",
10244
10501
  {
10245
10502
  onClick: hidePanel,
10246
10503
  className: headerIconButtonClass,
10247
- children: /* @__PURE__ */ jsxs21("svg", { className: headerIconClass, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: [
10504
+ children: /* @__PURE__ */ jsxs20("svg", { className: headerIconClass, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: [
10248
10505
  /* @__PURE__ */ jsx26("rect", { x: "3", y: "4", width: "18", height: "16", rx: "2", strokeLinecap: "round", strokeLinejoin: "round" }),
10249
10506
  /* @__PURE__ */ jsx26("path", { d: "M15 4v16", strokeLinecap: "round" })
10250
10507
  ] })
@@ -10252,13 +10509,13 @@ var CompactChat = memo18(function CompactChat2({
10252
10509
  ),
10253
10510
  /* @__PURE__ */ jsx26("div", { className: "chat-tooltip", children: mergedStrings.collapseSidebar })
10254
10511
  ] }),
10255
- /* @__PURE__ */ jsxs21("div", { className: "chat-tooltip-wrapper", children: [
10512
+ /* @__PURE__ */ jsxs20("div", { className: "chat-tooltip-wrapper", children: [
10256
10513
  /* @__PURE__ */ jsx26(
10257
10514
  "button",
10258
10515
  {
10259
10516
  onClick: toggleMode,
10260
10517
  className: headerIconButtonClass,
10261
- children: /* @__PURE__ */ jsxs21("svg", { className: headerIconClass, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: [
10518
+ children: /* @__PURE__ */ jsxs20("svg", { className: headerIconClass, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: [
10262
10519
  /* @__PURE__ */ jsx26("rect", { x: "8", y: "3", width: "13", height: "13", rx: "2", strokeLinecap: "round", strokeLinejoin: "round" }),
10263
10520
  /* @__PURE__ */ jsx26("path", { d: "M5 8H4a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-1", strokeLinecap: "round", strokeLinejoin: "round" })
10264
10521
  ] })
@@ -10266,7 +10523,7 @@ var CompactChat = memo18(function CompactChat2({
10266
10523
  ),
10267
10524
  /* @__PURE__ */ jsx26("div", { className: "chat-tooltip", children: mergedStrings.floatWindow })
10268
10525
  ] }),
10269
- /* @__PURE__ */ jsxs21("div", { className: "chat-tooltip-wrapper", children: [
10526
+ /* @__PURE__ */ jsxs20("div", { className: "chat-tooltip-wrapper", children: [
10270
10527
  /* @__PURE__ */ jsx26(
10271
10528
  "button",
10272
10529
  {
@@ -10277,7 +10534,7 @@ var CompactChat = memo18(function CompactChat2({
10277
10534
  ),
10278
10535
  /* @__PURE__ */ jsx26("div", { className: "chat-tooltip", children: mergedStrings.history || mergedStrings.recentChats })
10279
10536
  ] }),
10280
- /* @__PURE__ */ jsxs21("div", { className: "chat-tooltip-wrapper", children: [
10537
+ /* @__PURE__ */ jsxs20("div", { className: "chat-tooltip-wrapper", children: [
10281
10538
  /* @__PURE__ */ jsx26(
10282
10539
  "button",
10283
10540
  {
@@ -10286,7 +10543,7 @@ var CompactChat = memo18(function CompactChat2({
10286
10543
  children: /* @__PURE__ */ jsx26("svg", { className: headerIconClass, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: /* @__PURE__ */ jsx26("path", { d: "M12 5v14m-7-7h14", strokeLinecap: "round", strokeLinejoin: "round" }) })
10287
10544
  }
10288
10545
  ),
10289
- /* @__PURE__ */ jsxs21("div", { className: "chat-tooltip", children: [
10546
+ /* @__PURE__ */ jsxs20("div", { className: "chat-tooltip", children: [
10290
10547
  /* @__PURE__ */ jsx26("div", { children: mergedStrings.newChat || "New Chat" }),
10291
10548
  /* @__PURE__ */ jsx26("div", { className: "chat-tooltip-shortcut", children: shortcutKey })
10292
10549
  ] })
@@ -10295,15 +10552,15 @@ var CompactChat = memo18(function CompactChat2({
10295
10552
  ] })
10296
10553
  ) : (
10297
10554
  // Floating mode: original layout with logo, title, and right-aligned buttons
10298
- /* @__PURE__ */ jsxs21(Fragment6, { children: [
10299
- /* @__PURE__ */ jsx26("div", { className: "flex items-center gap-1", style: { WebkitAppRegion: "no-drag" }, children: headerLeft || /* @__PURE__ */ jsxs21("div", { className: "flex items-center gap-2", children: [
10555
+ /* @__PURE__ */ jsxs20(Fragment6, { children: [
10556
+ /* @__PURE__ */ jsx26("div", { className: "flex items-center gap-1", style: { WebkitAppRegion: "no-drag" }, children: headerLeft || /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-2", children: [
10300
10557
  logoNode,
10301
10558
  /* @__PURE__ */ jsx26("span", { className: "text-sm font-medium text-[var(--chat-text)]", children: headerTitle })
10302
10559
  ] }) }),
10303
10560
  /* @__PURE__ */ jsx26("div", { className: "flex-1" }),
10304
- /* @__PURE__ */ jsxs21("div", { className: "flex items-center gap-0.5", style: { WebkitAppRegion: "no-drag" }, children: [
10561
+ /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-0.5", style: { WebkitAppRegion: "no-drag" }, children: [
10305
10562
  /* @__PURE__ */ jsx26(PanelHeaderButtons, { locale: resolvedConfig?.locale }),
10306
- /* @__PURE__ */ jsxs21("div", { className: "chat-tooltip-wrapper", children: [
10563
+ /* @__PURE__ */ jsxs20("div", { className: "chat-tooltip-wrapper", children: [
10307
10564
  /* @__PURE__ */ jsx26(
10308
10565
  "button",
10309
10566
  {
@@ -10312,12 +10569,12 @@ var CompactChat = memo18(function CompactChat2({
10312
10569
  children: /* @__PURE__ */ jsx26("svg", { className: headerIconClass, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: /* @__PURE__ */ jsx26("path", { d: "M12 5v14m-7-7h14", strokeLinecap: "round", strokeLinejoin: "round" }) })
10313
10570
  }
10314
10571
  ),
10315
- /* @__PURE__ */ jsxs21("div", { className: "chat-tooltip", children: [
10572
+ /* @__PURE__ */ jsxs20("div", { className: "chat-tooltip", children: [
10316
10573
  /* @__PURE__ */ jsx26("div", { children: mergedStrings.newChat || "New Chat" }),
10317
10574
  /* @__PURE__ */ jsx26("div", { className: "chat-tooltip-shortcut", children: shortcutKey })
10318
10575
  ] })
10319
10576
  ] }),
10320
- /* @__PURE__ */ jsxs21("div", { className: "chat-tooltip-wrapper", children: [
10577
+ /* @__PURE__ */ jsxs20("div", { className: "chat-tooltip-wrapper", children: [
10321
10578
  /* @__PURE__ */ jsx26(
10322
10579
  "button",
10323
10580
  {
@@ -10328,7 +10585,7 @@ var CompactChat = memo18(function CompactChat2({
10328
10585
  ),
10329
10586
  /* @__PURE__ */ jsx26("div", { className: "chat-tooltip", children: mergedStrings.recentChats || "Recent Chats" })
10330
10587
  ] }),
10331
- showPin && /* @__PURE__ */ jsxs21("div", { className: "chat-tooltip-wrapper", children: [
10588
+ showPin && /* @__PURE__ */ jsxs20("div", { className: "chat-tooltip-wrapper", children: [
10332
10589
  /* @__PURE__ */ jsx26(
10333
10590
  "button",
10334
10591
  {
@@ -10336,13 +10593,13 @@ var CompactChat = memo18(function CompactChat2({
10336
10593
  className: headerIconButtonClass,
10337
10594
  children: /* @__PURE__ */ jsx26("svg", { className: headerIconClass, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: isPinned ? (
10338
10595
  // Pin (active state) - lucide pin
10339
- /* @__PURE__ */ jsxs21(Fragment6, { children: [
10596
+ /* @__PURE__ */ jsxs20(Fragment6, { children: [
10340
10597
  /* @__PURE__ */ jsx26("path", { d: "M12 17v5" }),
10341
10598
  /* @__PURE__ */ jsx26("path", { d: "M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H8a2 2 0 0 0 0 4 1 1 0 0 1 1 1z" })
10342
10599
  ] })
10343
10600
  ) : (
10344
10601
  // PinOff (inactive state) - lucide pin-off
10345
- /* @__PURE__ */ jsxs21(Fragment6, { children: [
10602
+ /* @__PURE__ */ jsxs20(Fragment6, { children: [
10346
10603
  /* @__PURE__ */ jsx26("path", { d: "M12 17v5" }),
10347
10604
  /* @__PURE__ */ jsx26("path", { d: "M15 9.34V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H7.89" }),
10348
10605
  /* @__PURE__ */ jsx26("path", { d: "m2 2 20 20" }),
@@ -10353,7 +10610,7 @@ var CompactChat = memo18(function CompactChat2({
10353
10610
  ),
10354
10611
  /* @__PURE__ */ jsx26("div", { className: "chat-tooltip", children: isPinned ? mergedStrings.unpin : mergedStrings.pin })
10355
10612
  ] }),
10356
- showClose && /* @__PURE__ */ jsxs21("div", { className: "chat-tooltip-wrapper", children: [
10613
+ showClose && /* @__PURE__ */ jsxs20("div", { className: "chat-tooltip-wrapper", children: [
10357
10614
  /* @__PURE__ */ jsx26(
10358
10615
  "button",
10359
10616
  {
@@ -10410,6 +10667,7 @@ var CompactChat = memo18(function CompactChat2({
10410
10667
  (() => {
10411
10668
  if (hideInput && !shouldRenderInputExternally) return null;
10412
10669
  const disableInput = !!chat.pendingInterrupt || chat.isLoading && !chat.isStreaming;
10670
+ const allowEmptySubmit = resourcePicker.attachedResources.length > 0 || chat.sessionResources.length > 0;
10413
10671
  const addResourceButtonSlot = resourceProviders.length > 0 ? /* @__PURE__ */ jsx26(
10414
10672
  AddResourceButton,
10415
10673
  {
@@ -10443,6 +10701,7 @@ var CompactChat = memo18(function CompactChat2({
10443
10701
  disabled: disableInput,
10444
10702
  isStreaming: chat.isStreaming,
10445
10703
  isLoading: chat.isLoading,
10704
+ allowEmptySubmit,
10446
10705
  autoFocus: true,
10447
10706
  leftSlot: addResourceButtonSlot
10448
10707
  }
@@ -10450,7 +10709,7 @@ var CompactChat = memo18(function CompactChat2({
10450
10709
  if (shouldRenderInputExternally && portalContainerRef.current) {
10451
10710
  return createPortal(inputElement, portalContainerRef.current);
10452
10711
  }
10453
- return /* @__PURE__ */ jsxs21("div", { className: "flex flex-col gap-2 px-3 pb-3 pt-1", children: [
10712
+ return /* @__PURE__ */ jsxs20("div", { className: "flex flex-col gap-2 px-3 pb-3 pt-1", children: [
10454
10713
  alert ? /* @__PURE__ */ jsx26(
10455
10714
  AlertBanner,
10456
10715
  {
@@ -10506,7 +10765,7 @@ var CompactChat = memo18(function CompactChat2({
10506
10765
  }
10507
10766
  }
10508
10767
  ),
10509
- (chat.sessionResources.length > 0 || resourcePicker.attachedResources.length > 0) && /* @__PURE__ */ jsxs21(Fragment6, { children: [
10768
+ (chat.sessionResources.length > 0 || resourcePicker.attachedResources.length > 0) && /* @__PURE__ */ jsxs20(Fragment6, { children: [
10510
10769
  chat.sessionResources.length > 0 && /* @__PURE__ */ jsx26(
10511
10770
  AttachedResourceTags,
10512
10771
  {
@@ -10590,5 +10849,6 @@ export {
10590
10849
  useResourcePicker,
10591
10850
  useStandaloneI18n,
10592
10851
  useStandaloneTheme,
10593
- useTheme
10852
+ useTheme,
10853
+ useWindowDragLock
10594
10854
  };