@zero-library/chat-copilot 3.1.9 → 3.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.esm.js CHANGED
@@ -1,7 +1,7 @@
1
- import { CloudUploadOutlined, PaperClipOutlined, createFromIconfontCN, LoadingOutlined, EnterOutlined, DownloadOutlined, CloseOutlined, PlayCircleOutlined, CopyOutlined, DotChartOutlined, LikeOutlined, DislikeOutlined, ToolOutlined, SearchOutlined, UpOutlined, DownOutlined, PlusOutlined, CommentOutlined, RedoOutlined, DeleteOutlined, ClockCircleOutlined, CheckCircleOutlined, FileImageOutlined, FilePdfOutlined, FileWordOutlined, FileExcelOutlined, FilePptOutlined, FileZipOutlined, FileTextOutlined, FileUnknownOutlined } from '@ant-design/icons';
1
+ import { CloudUploadOutlined, PaperClipOutlined, createFromIconfontCN, EnterOutlined, DownloadOutlined, CloseOutlined, PlayCircleOutlined, CopyOutlined, DotChartOutlined, LoadingOutlined, RightOutlined, LikeOutlined, DislikeOutlined, ToolOutlined, SearchOutlined, UpOutlined, DownOutlined, PlusOutlined, CommentOutlined, RedoOutlined, DeleteOutlined, ClockCircleOutlined, CheckCircleOutlined, FileImageOutlined, FilePdfOutlined, FileWordOutlined, FileExcelOutlined, FilePptOutlined, FileZipOutlined, FileTextOutlined, FileUnknownOutlined } from '@ant-design/icons';
2
2
  import { Attachments, Sender, FileCard, Bubble, Think, XProvider, Mermaid, CodeHighlighter, Welcome, Prompts, Conversations } from '@ant-design/x-v2';
3
- import { useRefState, useDebounce, createTokenManager, useSyncInput, isEmptyObj, markdownToText, RenderWrapper, shouldRender, isFunction, downloadFile, LuyaFilePreview, MarkdownEditor, useDeepEffect, isObject, useWebSocket, isNullOrUnDef, isNumber, getFileSuffixName, FileIcon, copyText, LazyComponent, isBoolean, UserAvatar, htmlToMarkdown, buildUrlParams, isExternal, deepCopy, transforms, deepMerge, createRequest, HttpStatus, isArray, isString, isDef, isNull, transform, emit, getWebSocketUrl, safeParseJson } from '@zero-library/common';
4
- import { App, Badge, Button, Flex, Typography, Tooltip, Layout, Tag, Spin, Splitter, Image as Image$1, Popover, Skeleton, Alert, theme, Collapse, Divider as Divider$1, Select as Select$1, Avatar, Space, Form, Drawer, Empty, Modal, Checkbox, Input, InputNumber, Switch as Switch$1, message, List, Upload, Card, Table, Progress as Progress$1 } from 'antd';
3
+ import { useRefState, useDebounce, createTokenManager, useSyncInput, isEmptyObj, markdownToText, RenderWrapper, shouldRender, isFunction, downloadFile, LuyaFilePreview, MarkdownEditor, useDeepEffect, isObject, useWebSocket, isNullOrUnDef, isNumber, getFileSuffixName, emit, FileIcon, copyText, LazyComponent, isBoolean, UserAvatar, htmlToMarkdown, buildUrlParams, isExternal, deepCopy, transforms, deepMerge, createRequest, HttpStatus, isArray, isString, isDef, isNull, transform, getWebSocketUrl, safeParseJson } from '@zero-library/common';
4
+ import { App, Badge, Button, Flex, Typography, Tooltip, Layout, Tag, Spin, Splitter, Image as Image$1, Popover, Skeleton, Alert, theme, Collapse, Divider as Divider$1, Select as Select$1, Avatar, Space, Form, Drawer, Empty, Modal, Checkbox, Input, InputNumber, Switch as Switch$1, message, Upload, List, Card, Table, Progress as Progress$1 } from 'antd';
5
5
  import * as React10 from 'react';
6
6
  import React10__default, { createContext, forwardRef, useRef, useEffect, useImperativeHandle, useMemo, memo, useState, useContext, useCallback, useLayoutEffect } from 'react';
7
7
  import { useSnapshot, proxy } from 'valtio';
@@ -1327,7 +1327,7 @@ function createChatStore() {
1327
1327
  };
1328
1328
  const setConversationSpec = (spec) => {
1329
1329
  if (isObject(spec)) {
1330
- Object.assign(conversation.active.spec, spec);
1330
+ Object.assign(conversation.active.spec || {}, spec);
1331
1331
  }
1332
1332
  };
1333
1333
  const setConversationUserInput = (userInput) => {
@@ -1372,9 +1372,14 @@ function createChatStore() {
1372
1372
  });
1373
1373
  conversation.messages[conversationId].message = [];
1374
1374
  if (data?.length) {
1375
- data.forEach((msg) => {
1375
+ const mainMessages = data.filter((msg) => !msg.toolCallId);
1376
+ const subAgentMessages = data.filter((msg) => msg.toolCallId);
1377
+ mainMessages.forEach((msg) => {
1376
1378
  processMessageContent(msg);
1377
1379
  });
1380
+ subAgentMessages.forEach((msg) => {
1381
+ routeSubAgentMessage(msg);
1382
+ });
1378
1383
  finalizeHistoryMessages(conversationId);
1379
1384
  normalizeMessagesByExecutionAndRole(conversation.messages[conversationId].message);
1380
1385
  }
@@ -1440,9 +1445,7 @@ function createChatStore() {
1440
1445
  item.generating = false;
1441
1446
  });
1442
1447
  }
1443
- function startCallback(msg) {
1444
- const messages = conversation.messages[msg.conversationId]?.message;
1445
- if (!messages) return;
1448
+ function startCallback(msg, messages, isMain) {
1446
1449
  const idx = findExecutionMsgIndex(msg, messages);
1447
1450
  const contentItem = msg.content[0];
1448
1451
  if (contentItem.type !== "runStarted") return;
@@ -1453,23 +1456,24 @@ function createChatStore() {
1453
1456
  generating: true
1454
1457
  };
1455
1458
  messages.push(finalMsg);
1456
- const targetConversation = conversations.list.items.find((item) => item.id === msg.conversationId);
1457
- if (targetConversation && msg.createdAt) {
1458
- updateConversations({
1459
- ...targetConversation,
1460
- id: targetConversation.id,
1461
- title: targetConversation.label,
1462
- updatedAt: msg.createdAt
1463
- });
1459
+ if (isMain) {
1460
+ const targetConversation = conversations.list.items.find((item) => item.id === msg.conversationId);
1461
+ if (targetConversation && msg.createdAt) {
1462
+ updateConversations({
1463
+ ...targetConversation,
1464
+ id: targetConversation.id,
1465
+ title: targetConversation.label,
1466
+ updatedAt: msg.createdAt
1467
+ });
1468
+ }
1464
1469
  }
1465
1470
  } else {
1466
1471
  const prevContent = messages[idx]?.content || [];
1467
1472
  messages[idx].content = [...prevContent, contentItem];
1468
1473
  }
1469
- conversation.messages[msg.conversationId].loading = true;
1474
+ if (isMain) conversation.messages[msg.conversationId].loading = true;
1470
1475
  }
1471
- function textCallback(msg) {
1472
- const messages = conversation.messages[msg.conversationId]?.message;
1476
+ function textCallback(msg, messages, isMain) {
1473
1477
  const idx = findExecutionMsgIndex(msg, messages);
1474
1478
  const contents = idx !== -1 && messages[idx] ? messages[idx].content || [] : [];
1475
1479
  const nextContent = msg.content[0];
@@ -1498,13 +1502,12 @@ function createChatStore() {
1498
1502
  messages[idx].content = [...contents, normalizedNextContent];
1499
1503
  }
1500
1504
  }
1501
- conversation.messages[msg.conversationId].loading = true;
1505
+ if (isMain) conversation.messages[msg.conversationId].loading = true;
1502
1506
  }
1503
- function stepStartedCallback(msg) {
1504
- const messages = conversation.messages[msg.conversationId]?.message;
1507
+ function stepStartedCallback(msg, messages, isMain) {
1505
1508
  const idx = findExecutionMsgIndex(msg, messages);
1506
1509
  const contentItem = msg.content[0];
1507
- conversation.messages[msg.conversationId].loading = true;
1510
+ if (isMain) conversation.messages[msg.conversationId].loading = true;
1508
1511
  if (idx !== -1 && messages[idx]) {
1509
1512
  const contentList = messages[idx].content || [];
1510
1513
  const runStartedIndex = contentList.findIndex((item) => item.type === "runStarted");
@@ -1514,52 +1517,60 @@ function createChatStore() {
1514
1517
  messages[idx].content = contentList.map((item, i) => i === runStartedIndex ? nextRunStartedItem : item);
1515
1518
  }
1516
1519
  }
1520
+ if (isMain) config.hooks?.onStepMessage?.(msg);
1517
1521
  config.hooks?.onStepMessage?.(msg);
1518
1522
  }
1519
- function stepFinishedCallback(msg) {
1520
- conversation.messages[msg.conversationId].loading = true;
1521
- config.hooks?.onStepMessage?.(msg);
1523
+ function stepFinishedCallback(msg, _messages, isMain) {
1524
+ if (isMain) conversation.messages[msg.conversationId].loading = true;
1525
+ if (isMain) config.hooks?.onStepMessage?.(msg);
1522
1526
  }
1523
- function stepErrCallback(msg) {
1524
- conversation.messages[msg.conversationId].loading = false;
1525
- const messages = conversation.messages[msg.conversationId]?.message;
1526
- if (messages) {
1527
- const idx = findExecutionMsgIndex(msg, messages);
1528
- const contentItem = msg.content[0];
1529
- messages.forEach((item) => {
1530
- if (item.executionId === msg.executionId) {
1531
- item.generating = false;
1532
- }
1533
- });
1534
- if (idx !== -1) {
1535
- messages[idx].generating = false;
1536
- }
1537
- if (idx !== -1) {
1538
- const prevContent = messages[idx]?.content || [];
1539
- messages[idx].content = [...prevContent, contentItem];
1540
- } else {
1541
- const finalMsg = { ...msg };
1542
- finalMsg.generating = false;
1543
- messages.push(finalMsg);
1527
+ function stepErrCallback(msg, messages, isMain) {
1528
+ if (isMain) conversation.messages[msg.conversationId].loading = false;
1529
+ const idx = findExecutionMsgIndex(msg, messages);
1530
+ const contentItem = msg.content[0];
1531
+ messages.forEach((item) => {
1532
+ if (item.executionId === msg.executionId) {
1533
+ item.generating = false;
1544
1534
  }
1535
+ });
1536
+ if (idx !== -1) {
1537
+ messages[idx].generating = false;
1538
+ const prevContent = messages[idx]?.content || [];
1539
+ messages[idx].content = [...prevContent, contentItem];
1540
+ } else {
1541
+ const finalMsg = { ...msg };
1542
+ finalMsg.generating = false;
1543
+ messages.push(finalMsg);
1545
1544
  }
1546
- config.hooks?.onStepMessage?.(msg);
1545
+ if (isMain) config.hooks?.onStepMessage?.(msg);
1547
1546
  }
1548
- function doneCallback(msg) {
1547
+ function doneCallback(msg, message3, isMain) {
1549
1548
  conversation.messages[msg.conversationId].loading = false;
1550
1549
  const messages = conversation.messages[msg.conversationId]?.message;
1551
1550
  if (messages) {
1551
+ const idx = findExecutionMsgIndex(msg, messages);
1552
+ const contentItem = msg.content[0];
1552
1553
  messages.forEach((item) => {
1553
1554
  if (item.executionId === msg.executionId) {
1554
1555
  item.generating = false;
1555
1556
  }
1556
1557
  });
1558
+ if (contentItem?.type === "runFailed") {
1559
+ if (idx !== -1) {
1560
+ const prevContent = messages[idx]?.content || [];
1561
+ messages[idx].content = [...prevContent, contentItem];
1562
+ } else {
1563
+ const finalMsg = { ...msg, generating: false };
1564
+ messages.push(finalMsg);
1565
+ }
1566
+ }
1557
1567
  }
1558
- config.hooks?.onAfterAcceptMessage?.(msg);
1568
+ if (isMain) config.hooks?.onAfterAcceptMessage?.(msg);
1559
1569
  }
1560
- function titleCallback(msg) {
1570
+ function titleCallback(msg, _messages, isMain) {
1561
1571
  const content = msg.content[0];
1562
1572
  if (content.type !== "conversationNewTitle") return;
1573
+ if (!isMain) return;
1563
1574
  const title = content.title || "";
1564
1575
  const conversationId = msg.conversationId || "";
1565
1576
  if (content && conversations.list.items.length) {
@@ -1568,9 +1579,7 @@ function createChatStore() {
1568
1579
  conversations.list.items[idx].label = title;
1569
1580
  }
1570
1581
  }
1571
- function toolCallCallback(msg) {
1572
- const messages = conversation.messages[msg.conversationId]?.message;
1573
- if (!messages) return;
1582
+ function toolCallCallback(msg, messages, isMain) {
1574
1583
  let idx = -1;
1575
1584
  const contentItem = msg.content[0];
1576
1585
  if (contentItem.type !== "toolCall") return;
@@ -1606,16 +1615,20 @@ function createChatStore() {
1606
1615
  if (contentItem.status) {
1607
1616
  nextItem.status = contentItem.status;
1608
1617
  }
1618
+ if (contentItem.toolIcon) {
1619
+ nextItem.toolIcon = contentItem.toolIcon;
1620
+ }
1621
+ if (contentItem.display) {
1622
+ nextItem.display = (existingItem.display || "") + contentItem.display;
1623
+ }
1609
1624
  messages[idx].content = contents.map((item, i) => i === existingItemIndex ? nextItem : item);
1610
1625
  } else {
1611
1626
  messages[idx].content = [...contents, contentItem];
1612
1627
  }
1613
1628
  }
1614
- conversation.messages[msg.conversationId].loading = true;
1629
+ if (isMain) conversation.messages[msg.conversationId].loading = true;
1615
1630
  }
1616
- function toolResultCallback(msg) {
1617
- const messages = conversation.messages[msg.conversationId]?.message;
1618
- if (!messages) return;
1631
+ function toolResultCallback(msg, messages, isMain) {
1619
1632
  const contentItem = msg.content[0];
1620
1633
  if (contentItem.type !== "toolResult") return;
1621
1634
  let idx = -1;
@@ -1646,15 +1659,16 @@ function createChatStore() {
1646
1659
  if (contentItem.title) {
1647
1660
  nextToolCallItem.title = contentItem.title;
1648
1661
  }
1662
+ if (contentItem.display !== void 0) {
1663
+ nextToolCallItem.display = contentItem.display;
1664
+ }
1649
1665
  messages[idx].content = contents.map((item, i) => i === toolCallIndex ? nextToolCallItem : item);
1650
1666
  } else {
1651
1667
  messages[idx].content = [...contents, contentItem];
1652
1668
  }
1653
- conversation.messages[msg.conversationId].loading = true;
1669
+ if (isMain) conversation.messages[msg.conversationId].loading = true;
1654
1670
  }
1655
- function a2uiCommandCallback(msg) {
1656
- const messages = conversation.messages[msg.conversationId]?.message;
1657
- if (!messages) return;
1671
+ function a2uiCommandCallback(msg, messages, isMain) {
1658
1672
  const idx = findExecutionMsgIndex(msg, messages);
1659
1673
  const contentItem = msg.content[0];
1660
1674
  if (contentItem.type !== "a2uiCommand") return;
@@ -1665,45 +1679,147 @@ function createChatStore() {
1665
1679
  const prevContent = messages[idx]?.content || [];
1666
1680
  messages[idx].content = [...prevContent, contentItem];
1667
1681
  }
1668
- conversation.messages[msg.conversationId].loading = true;
1682
+ if (isMain) conversation.messages[msg.conversationId].loading = true;
1683
+ }
1684
+ function toolCallDeltaCallback(msg, messages, isMain) {
1685
+ const contentItem = msg.content[0];
1686
+ if (contentItem.type !== "toolCallDelta") return;
1687
+ let idx = -1;
1688
+ if (contentItem.toolCallId) {
1689
+ idx = messages.findLastIndex(
1690
+ (m) => m.content?.some((c) => (c.type === "toolCall" || c.type === "toolCallDelta") && c.toolCallId === contentItem.toolCallId)
1691
+ );
1692
+ }
1693
+ if (idx === -1) idx = findExecutionMsgIndex(msg, messages);
1694
+ if (idx === -1) {
1695
+ messages.push({
1696
+ ...msg,
1697
+ content: [
1698
+ {
1699
+ type: "toolCall",
1700
+ toolCallId: contentItem.toolCallId,
1701
+ toolName: contentItem.toolName || void 0,
1702
+ toolIcon: contentItem.toolIcon,
1703
+ title: contentItem.title,
1704
+ content: contentItem.argumentsDelta || "",
1705
+ display: contentItem.display,
1706
+ status: contentItem.status || "running"
1707
+ }
1708
+ ],
1709
+ generating: true
1710
+ });
1711
+ } else {
1712
+ const contents = messages[idx].content;
1713
+ const itemIdx = contents.findIndex(
1714
+ (c) => (c.type === "toolCall" || c.type === "toolCallDelta") && c.toolCallId === contentItem.toolCallId
1715
+ );
1716
+ if (itemIdx !== -1) {
1717
+ const existing = contents[itemIdx];
1718
+ const nextItem = {
1719
+ ...existing,
1720
+ type: "toolCall",
1721
+ content: (existing.content || "") + (contentItem.argumentsDelta || "")
1722
+ };
1723
+ if (contentItem.toolName) nextItem.toolName = contentItem.toolName;
1724
+ if (contentItem.title) nextItem.title = contentItem.title;
1725
+ if (contentItem.status) nextItem.status = contentItem.status;
1726
+ if (contentItem.toolIcon) nextItem.toolIcon = contentItem.toolIcon;
1727
+ if (contentItem.display) nextItem.display = (existing.display || "") + contentItem.display;
1728
+ messages[idx].content = contents.map((c, i) => i === itemIdx ? nextItem : c);
1729
+ } else {
1730
+ messages[idx].content = [
1731
+ ...contents,
1732
+ {
1733
+ type: "toolCall",
1734
+ toolCallId: contentItem.toolCallId,
1735
+ toolName: contentItem.toolName || void 0,
1736
+ toolIcon: contentItem.toolIcon,
1737
+ title: contentItem.title,
1738
+ content: contentItem.argumentsDelta || "",
1739
+ display: contentItem.display,
1740
+ status: contentItem.status || "running"
1741
+ }
1742
+ ];
1743
+ }
1744
+ }
1745
+ if (isMain) conversation.messages[msg.conversationId].loading = true;
1746
+ }
1747
+ function findToolCallItemRecursive(messages, toolCallId) {
1748
+ for (let i = messages.length - 1; i >= 0; i--) {
1749
+ const msg = messages[i];
1750
+ const contents = msg.content || [];
1751
+ const itemIdx = contents.findIndex((c) => c.type === "toolCall" && c.toolCallId === toolCallId);
1752
+ if (itemIdx !== -1) {
1753
+ return { messageList: msg, itemIndex: itemIdx };
1754
+ }
1755
+ for (const content of contents) {
1756
+ if (content.type === "toolCall") {
1757
+ const subMessages = content.subMessages;
1758
+ if (subMessages?.length) {
1759
+ const found = findToolCallItemRecursive(subMessages, toolCallId);
1760
+ if (found) return found;
1761
+ }
1762
+ }
1763
+ }
1764
+ }
1765
+ return null;
1766
+ }
1767
+ function routeSubAgentMessage(msg) {
1768
+ const conversationId = msg.conversationId;
1769
+ const mainMessages = conversation.messages[conversationId]?.message;
1770
+ if (!mainMessages) return;
1771
+ const found = findToolCallItemRecursive(mainMessages, msg.toolCallId);
1772
+ if (!found) {
1773
+ return;
1774
+ }
1775
+ const { messageList, itemIndex } = found;
1776
+ const contents = messageList.content;
1777
+ const toolCallItem = contents[itemIndex];
1778
+ toolCallItem.hasSubAgent = true;
1779
+ if (!toolCallItem.subMessages) {
1780
+ toolCallItem.subMessages = [];
1781
+ }
1782
+ processMessageContent(msg, toolCallItem.subMessages);
1783
+ messageList.content = contents.map((c, i) => i === itemIndex ? { ...toolCallItem } : c);
1669
1784
  }
1670
- function processSingleMessageContent(newMessage) {
1785
+ function processSingleMessageContent(newMessage, messages, isMain) {
1671
1786
  switch (newMessage.content[0].type) {
1672
1787
  case "runStarted":
1673
- startCallback(newMessage);
1788
+ startCallback(newMessage, messages, isMain);
1674
1789
  break;
1675
1790
  case "text":
1676
- textCallback(newMessage);
1791
+ textCallback(newMessage, messages, isMain);
1677
1792
  break;
1678
1793
  case "stepStarted":
1679
- stepStartedCallback(newMessage);
1794
+ stepStartedCallback(newMessage, messages, isMain);
1680
1795
  break;
1681
1796
  case "stepFinished":
1682
- stepFinishedCallback(newMessage);
1797
+ stepFinishedCallback(newMessage, messages, isMain);
1683
1798
  break;
1684
1799
  case "stepError":
1685
- stepErrCallback(newMessage);
1800
+ stepErrCallback(newMessage, messages, isMain);
1686
1801
  break;
1687
1802
  case "runFinished":
1688
1803
  case "runFailed":
1689
1804
  case "runStopped":
1690
- doneCallback(newMessage);
1805
+ doneCallback(newMessage, messages, isMain);
1691
1806
  break;
1692
1807
  case "conversationNewTitle":
1693
- titleCallback(newMessage);
1808
+ titleCallback(newMessage, messages, isMain);
1694
1809
  break;
1695
1810
  case "toolCall":
1696
- toolCallCallback(newMessage);
1811
+ toolCallCallback(newMessage, messages, isMain);
1812
+ break;
1813
+ case "toolCallDelta":
1814
+ toolCallDeltaCallback(newMessage, messages, isMain);
1697
1815
  break;
1698
1816
  case "toolResult":
1699
- toolResultCallback(newMessage);
1817
+ toolResultCallback(newMessage, messages, isMain);
1700
1818
  break;
1701
1819
  case "a2uiCommand":
1702
- a2uiCommandCallback(newMessage);
1820
+ a2uiCommandCallback(newMessage, messages, isMain);
1703
1821
  break;
1704
1822
  default: {
1705
- const messages = conversation.messages[newMessage.conversationId]?.message;
1706
- if (!messages) return;
1707
1823
  const idx = findExecutionMsgIndex(newMessage, messages);
1708
1824
  if (idx === -1) {
1709
1825
  const finalMsg = { ...newMessage, generating: true };
@@ -1712,20 +1828,21 @@ function createChatStore() {
1712
1828
  const prevContent = messages[idx]?.content || [];
1713
1829
  messages[idx].content = [...prevContent, ...newMessage.content];
1714
1830
  }
1715
- conversation.messages[newMessage.conversationId].loading = true;
1831
+ if (isMain) conversation.messages[newMessage.conversationId].loading = true;
1716
1832
  break;
1717
1833
  }
1718
1834
  }
1719
1835
  }
1720
- function processMessageContent(message3) {
1836
+ function processMessageContent(message3, targetMessages) {
1721
1837
  const newMessage = {
1722
1838
  ...message3,
1723
1839
  agentId: agent.agentInfo.id
1724
1840
  };
1841
+ const isMain = !targetMessages;
1842
+ const messages = targetMessages ?? conversation.messages[newMessage.conversationId]?.message;
1843
+ if (!messages) return;
1725
1844
  const contentList = Array.isArray(newMessage.content) ? newMessage.content : [];
1726
1845
  if (contentList.length === 0) {
1727
- const messages = conversation.messages[newMessage.conversationId]?.message;
1728
- if (!messages) return;
1729
1846
  const idx = findExecutionMsgIndex(newMessage, messages);
1730
1847
  if (idx === -1) {
1731
1848
  messages.push({ ...newMessage });
@@ -1741,17 +1858,32 @@ function createChatStore() {
1741
1858
  return;
1742
1859
  }
1743
1860
  contentList.forEach((contentItem) => {
1744
- processSingleMessageContent({
1745
- ...newMessage,
1746
- content: [contentItem]
1747
- });
1861
+ processSingleMessageContent(
1862
+ {
1863
+ ...newMessage,
1864
+ content: [contentItem]
1865
+ },
1866
+ messages,
1867
+ isMain
1868
+ );
1748
1869
  });
1749
- normalizeMessagesByExecutionAndRole(conversation.messages[newMessage.conversationId]?.message);
1870
+ normalizeMessagesByExecutionAndRole(messages);
1750
1871
  }
1751
1872
  function isStoppedIncomingMessage(newMessage) {
1752
1873
  const messages = conversation.messages[newMessage.conversationId]?.message;
1753
1874
  if (!messages) return false;
1754
- return messages.some((item) => item.stopFlag && item.executionId === newMessage.executionId);
1875
+ if (messages.some((item) => item.stopFlag && item.executionId === newMessage.executionId)) {
1876
+ return true;
1877
+ }
1878
+ return messages.some(
1879
+ (msg) => msg.content?.some((c) => {
1880
+ if (c.type === "toolCall") {
1881
+ const subMessages = c.subMessages;
1882
+ return subMessages?.some((sub) => sub.stopFlag && sub.executionId === newMessage.executionId);
1883
+ }
1884
+ return false;
1885
+ })
1886
+ );
1755
1887
  }
1756
1888
  const acceptMessage = async (newMessage) => {
1757
1889
  const conversationId = newMessage.conversationId;
@@ -1761,6 +1893,10 @@ function createChatStore() {
1761
1893
  if (canProceed === false) {
1762
1894
  throw new Error("\u64CD\u4F5C\u88AB\u963B\u6B62");
1763
1895
  }
1896
+ if (newMessage.toolCallId) {
1897
+ routeSubAgentMessage(newMessage);
1898
+ return;
1899
+ }
1764
1900
  if (isStoppedIncomingMessage(newMessage)) {
1765
1901
  conversation.messages[conversationId].loading = false;
1766
1902
  return;
@@ -1842,19 +1978,25 @@ function createChatStore() {
1842
1978
  const lastMsg = messages[messages.length - 1];
1843
1979
  if (lastMsg.executionId) {
1844
1980
  await config.services.request.cancelMessage(lastMsg.executionId);
1845
- messages.forEach((item) => {
1846
- if (item.executionId === lastMsg.executionId) {
1847
- item.generating = false;
1848
- item.stopFlag = true;
1981
+ const markStopped = (msgList, matchExecutionId) => {
1982
+ msgList.forEach((item) => {
1983
+ if (item.executionId === lastMsg.executionId) {
1984
+ item.generating = false;
1985
+ item.stopFlag = true;
1986
+ }
1849
1987
  if (item.content && Array.isArray(item.content)) {
1850
1988
  item.content.forEach((contentItem) => {
1851
1989
  if (contentItem.type === "toolCall" && contentItem.status !== "success" && contentItem.status !== "error") {
1852
1990
  contentItem.status = "error";
1853
1991
  }
1992
+ if (contentItem.subMessages?.length) {
1993
+ markStopped(contentItem.subMessages);
1994
+ }
1854
1995
  });
1855
1996
  }
1856
- }
1857
- });
1997
+ });
1998
+ };
1999
+ markStopped(messages);
1858
2000
  } else {
1859
2001
  lastMsg.stopFlag = true;
1860
2002
  lastMsg.generating = false;
@@ -2591,6 +2733,7 @@ var AgentNavigate_default = memo(({ data }) => {
2591
2733
  }, [data]);
2592
2734
  const handleClick = () => {
2593
2735
  if (!content?.emit) return;
2736
+ emit(content.emit, { ...content.data, name: "luya-web-drawer" }, "nearest");
2594
2737
  };
2595
2738
  return /* @__PURE__ */ jsx(Button, { onClick: handleClick, style: { padding: 0 }, type: "link", children: content?.name || "\u70B9\u51FB\u6B64\u5904" });
2596
2739
  });
@@ -2801,9 +2944,7 @@ var MdEdit_default = ({ data, loading }) => {
2801
2944
  };
2802
2945
  var PreviewLink_default = ({ data, loading, message: message3, ...rest }) => {
2803
2946
  const chatStore = useChatStore();
2804
- const getLinkFileName = (href) => {
2805
- const url = new URL(href, window.location.origin);
2806
- const path = url.searchParams.get("path") || url.pathname;
2947
+ const getLinkFileName = (path) => {
2807
2948
  const lastSegment = path.split("/").pop();
2808
2949
  if (!lastSegment) {
2809
2950
  return "link";
@@ -2814,24 +2955,12 @@ var PreviewLink_default = ({ data, loading, message: message3, ...rest }) => {
2814
2955
  return lastSegment;
2815
2956
  }
2816
2957
  };
2817
- const getPreviewFileUrl = (href) => {
2818
- return buildUrlParams({ [TOKEN_KEY]: tokenManager.get() || "" }, href);
2819
- };
2820
- const handlePreviewLink = (href) => {
2821
- const fileName = getLinkFileName(href);
2822
- const suffix = getFileSuffixName(fileName);
2823
- chatStore.setPreview({
2824
- fileUrl: getPreviewFileUrl(href),
2825
- fileName,
2826
- suffix
2827
- });
2828
- };
2829
- const handlePathToUrl = (href) => {
2830
- const fileName = getLinkFileName(href);
2958
+ const handlePreviewByPath = (path) => {
2959
+ const fileName = getLinkFileName(path);
2831
2960
  const suffix = getFileSuffixName(fileName);
2832
2961
  chatStore.setPreview({
2833
2962
  fileUrl: chatStore.config.services.request.getPreviewUrl({
2834
- path: href,
2963
+ path,
2835
2964
  workspaceId: message3.conversationId
2836
2965
  }),
2837
2966
  fileName,
@@ -2845,12 +2974,18 @@ var PreviewLink_default = ({ data, loading, message: message3, ...rest }) => {
2845
2974
  return;
2846
2975
  }
2847
2976
  e.preventDefault();
2848
- if (String(rest.href).startsWith("/luya")) {
2849
- handlePreviewLink(href);
2977
+ if (String(rest.href).startsWith("/luya") || String(rest.href).startsWith("/agents")) {
2978
+ const url = new URL(href, window.location.origin);
2979
+ const path = url.searchParams.get("path");
2980
+ if (!path) {
2981
+ window.open(href, "_blank");
2982
+ return;
2983
+ }
2984
+ handlePreviewByPath(path);
2850
2985
  return;
2851
2986
  }
2852
2987
  if (String(rest.href).startsWith("/workspace")) {
2853
- handlePathToUrl(href);
2988
+ handlePreviewByPath(href);
2854
2989
  return;
2855
2990
  }
2856
2991
  window.open(href, "_blank");
@@ -3359,11 +3494,8 @@ var A2uiComponents = {
3359
3494
 
3360
3495
  // src/components/CustomComponents/A2uiRuntime/controller/extract.ts
3361
3496
  var A2UI_TAG_REGEX = /<A2UI\s+id="([^"]*)"\s*>([\s\S]*?)<\/A2UI>/g;
3362
- function hasA2uiTag(text) {
3363
- return typeof text === "string" && text.includes("<A2UI");
3364
- }
3365
3497
  function parseA2uiTagsFromText(text) {
3366
- if (!hasA2uiTag(text)) return [];
3498
+ if (typeof text !== "string" || !text.includes("<A2UI")) return [];
3367
3499
  const tags = [];
3368
3500
  const regex = new RegExp(A2UI_TAG_REGEX);
3369
3501
  let match;
@@ -3381,61 +3513,17 @@ function parseA2uiTagsFromText(text) {
3381
3513
  return tags;
3382
3514
  }
3383
3515
  function stripA2uiTags(text) {
3384
- if (!hasA2uiTag(text)) return text;
3385
- let result = text.replace(A2UI_TAG_REGEX, "");
3386
- result = result.replace(/<A2UI\b[\s\S]*$/, "");
3387
- return result.trim();
3388
- }
3389
- function splitA2uiTextSegments(text) {
3390
- if (typeof text !== "string" || !text.includes("<A2UI")) {
3391
- return text ? [{ type: "text", content: text }] : [];
3392
- }
3393
- const segments = [];
3394
- const regex = new RegExp(A2UI_TAG_REGEX);
3395
- let lastIndex = 0;
3396
- let match;
3397
- while ((match = regex.exec(text)) !== null) {
3398
- if (match.index > lastIndex) {
3399
- const before = text.slice(lastIndex, match.index);
3400
- if (before) segments.push({ type: "text", content: before });
3401
- }
3402
- const json = match[2].trim();
3403
- if (json) {
3404
- try {
3405
- const parsed = JSON.parse(json);
3406
- const commands = Array.isArray(parsed) ? parsed : [parsed];
3407
- const surfaceIds = commands.map((cmd) => String(cmd?.createSurface?.surfaceId || "").trim()).filter(Boolean);
3408
- if (surfaceIds.length) {
3409
- segments.push({ type: "a2ui", surfaceIds });
3410
- }
3411
- } catch {
3412
- }
3413
- }
3414
- lastIndex = regex.lastIndex;
3415
- }
3416
- if (lastIndex < text.length) {
3417
- let remaining = text.slice(lastIndex);
3418
- remaining = remaining.replace(/<A2UI\b[\s\S]*$/, "");
3419
- if (remaining) segments.push({ type: "text", content: remaining });
3420
- }
3421
- return segments.length ? segments : [];
3516
+ if (typeof text !== "string" || !text.includes("<A2UI")) return text;
3517
+ return text.replace(A2UI_TAG_REGEX, "").trim();
3422
3518
  }
3423
- function extractInlineSurfaceIdsFromMessage(message3) {
3424
- const surfaceIds = /* @__PURE__ */ new Set();
3425
- const items = Array.isArray(message3?.content) ? message3.content : [];
3426
- for (const item of items) {
3427
- if (item?.type !== "text") continue;
3428
- const text = item.messageContent || item.text || "";
3429
- if (typeof text !== "string" || !text.includes("<A2UI")) continue;
3430
- const tags = parseA2uiTagsFromText(text);
3431
- for (const tag of tags) {
3432
- for (const cmd of tag.commands) {
3433
- const sid = String(cmd?.createSurface?.surfaceId || "").trim();
3434
- if (sid) surfaceIds.add(sid);
3435
- }
3436
- }
3519
+ function extractItemTextForA2ui(item) {
3520
+ if (!item || item.type !== "toolCall") return "";
3521
+ const result = item.result;
3522
+ if (typeof result === "string") return result;
3523
+ if (result && typeof result === "object" && typeof result.stdout === "string") {
3524
+ return result.stdout;
3437
3525
  }
3438
- return surfaceIds;
3526
+ return "";
3439
3527
  }
3440
3528
  function extractDismissedSurfaceIdsFromMessages(messages) {
3441
3529
  const lastCreateIndexBySurface = /* @__PURE__ */ new Map();
@@ -3449,15 +3537,13 @@ function extractDismissedSurfaceIdsFromMessages(messages) {
3449
3537
  const surfaceId = String(item.command?.createSurface?.surfaceId || "").trim();
3450
3538
  if (surfaceId) lastCreateIndexBySurface.set(surfaceId, messageIndex);
3451
3539
  }
3452
- if (item?.type === "text") {
3453
- const text = item.messageContent || item.text || "";
3454
- if (typeof text === "string" && text.includes("<A2UI")) {
3455
- const tags = parseA2uiTagsFromText(text);
3456
- for (const tag of tags) {
3457
- for (const cmd of tag.commands) {
3458
- const surfaceId = String(cmd?.createSurface?.surfaceId || "").trim();
3459
- if (surfaceId) lastCreateIndexBySurface.set(surfaceId, messageIndex);
3460
- }
3540
+ const text = extractItemTextForA2ui(item);
3541
+ if (typeof text === "string" && text.includes("<A2UI")) {
3542
+ const tags = parseA2uiTagsFromText(text);
3543
+ for (const tag of tags) {
3544
+ for (const cmd of tag.commands) {
3545
+ const surfaceId = String(cmd?.createSurface?.surfaceId || "").trim();
3546
+ if (surfaceId) lastCreateIndexBySurface.set(surfaceId, messageIndex);
3461
3547
  }
3462
3548
  }
3463
3549
  }
@@ -3984,28 +4070,6 @@ function sanitizeA2uiCommands(commands) {
3984
4070
  return rest;
3985
4071
  });
3986
4072
  }
3987
- function diffConversationMessages(messages, prevCursors) {
3988
- if (messages.length < prevCursors.length) {
3989
- return { shouldReplayAll: true, nextCursors: [], pendingItems: [] };
3990
- }
3991
- const nextCursors = [];
3992
- const pendingItems = [];
3993
- for (let messageIndex = 0; messageIndex < messages.length; messageIndex += 1) {
3994
- const message3 = messages[messageIndex];
3995
- const messageId = String(message3?.messageId ?? messageIndex);
3996
- const items = Array.isArray(message3?.content) ? message3.content : [];
3997
- const prevCursor = prevCursors[messageIndex];
3998
- const startIndex = prevCursor ? prevCursor.contentLength : 0;
3999
- if (prevCursor && (prevCursor.messageId !== messageId || items.length < prevCursor.contentLength)) {
4000
- return { shouldReplayAll: true, nextCursors: [], pendingItems: [] };
4001
- }
4002
- for (let itemIndex = startIndex; itemIndex < items.length; itemIndex += 1) {
4003
- pendingItems.push({ messageIndex, messageId, item: items[itemIndex] });
4004
- }
4005
- nextCursors.push({ messageId, contentLength: items.length });
4006
- }
4007
- return { shouldReplayAll: false, nextCursors, pendingItems };
4008
- }
4009
4073
  function initializeWizardSurface(state, surfaceId, effects, nextWizardSteps) {
4010
4074
  const wizard = state.wizardSchemaBySurface[surfaceId];
4011
4075
  const createCommandIndex = state.latestCreateCommandIndexBySurface[surfaceId];
@@ -4025,6 +4089,10 @@ function initializeWizardSurface(state, surfaceId, effects, nextWizardSteps) {
4025
4089
  function processA2uiCommand(cmd, messageIndex, messageId, nextState, effects, deletedSurfaceIds, nextWizardSteps) {
4026
4090
  nextState.serverCommands.push(cmd);
4027
4091
  nextState.lastA2uiHost = { id: messageId, index: messageIndex };
4092
+ const wizardSchema = normalizeWizardSchema(cmd);
4093
+ if (wizardSchema) {
4094
+ nextState.wizardSchemaBySurface[wizardSchema.surfaceId] = wizardSchema;
4095
+ }
4028
4096
  const surfaceId = extractSurfaceId2(cmd);
4029
4097
  if (!surfaceId) return;
4030
4098
  if (cmd?.createSurface) {
@@ -4035,6 +4103,11 @@ function processA2uiCommand(cmd, messageIndex, messageId, nextState, effects, de
4035
4103
  if (cmd?.createSurface) {
4036
4104
  nextState.latestCreateCommandIndexBySurface[surfaceId] = nextState.serverCommands.length - 1;
4037
4105
  nextState.optimisticallyDismissedSurfaceIds = nextState.optimisticallyDismissedSurfaceIds.filter((id) => id !== surfaceId);
4106
+ const schemaSource = cmd.createSurface.schema ?? cmd.createSurface.wizard ?? cmd.createSurface.plan;
4107
+ const schema = normalizeWizardSchema(schemaSource) ?? normalizeWizardSchema(cmd.createSurface);
4108
+ if (schema) {
4109
+ nextState.wizardSchemaBySurface[surfaceId] = schema;
4110
+ }
4038
4111
  initializeWizardSurface(nextState, surfaceId, effects, nextWizardSteps);
4039
4112
  }
4040
4113
  if (cmd?.updateDataModel) {
@@ -4051,6 +4124,28 @@ function processA2uiCommand(cmd, messageIndex, messageId, nextState, effects, de
4051
4124
  delete nextState.modelPathBySurface[surfaceId];
4052
4125
  }
4053
4126
  }
4127
+ function diffConversationMessages(messages, prevCursors) {
4128
+ if (messages.length < prevCursors.length) {
4129
+ return { shouldReplayAll: true, nextCursors: [], pendingItems: [] };
4130
+ }
4131
+ const nextCursors = [];
4132
+ const pendingItems = [];
4133
+ for (let messageIndex = 0; messageIndex < messages.length; messageIndex += 1) {
4134
+ const message3 = messages[messageIndex];
4135
+ const messageId = String(message3?.messageId ?? messageIndex);
4136
+ const items = Array.isArray(message3?.content) ? message3.content : [];
4137
+ const prevCursor = prevCursors[messageIndex];
4138
+ const startIndex = prevCursor ? prevCursor.contentLength : 0;
4139
+ if (prevCursor && (prevCursor.messageId !== messageId || items.length < prevCursor.contentLength)) {
4140
+ return { shouldReplayAll: true, nextCursors: [], pendingItems: [] };
4141
+ }
4142
+ for (let itemIndex = startIndex; itemIndex < items.length; itemIndex += 1) {
4143
+ pendingItems.push({ messageIndex, messageId, item: items[itemIndex] });
4144
+ }
4145
+ nextCursors.push({ messageId, contentLength: items.length });
4146
+ }
4147
+ return { shouldReplayAll: false, nextCursors, pendingItems };
4148
+ }
4054
4149
  function scanA2uiTagsFromMessages(messages, processedTagIds) {
4055
4150
  const newTags = [];
4056
4151
  const newTagIds = [];
@@ -4059,8 +4154,7 @@ function scanA2uiTagsFromMessages(messages, processedTagIds) {
4059
4154
  const messageId = String(message3?.messageId ?? messageIndex);
4060
4155
  const items = Array.isArray(message3?.content) ? message3.content : [];
4061
4156
  for (const item of items) {
4062
- if (item?.type !== "text") continue;
4063
- const text = item.messageContent || item.text || "";
4157
+ const text = extractItemTextForA2ui(item);
4064
4158
  if (typeof text !== "string" || !text.includes("<A2UI")) continue;
4065
4159
  const tags = parseA2uiTagsFromText(text);
4066
4160
  for (const tag of tags) {
@@ -4075,14 +4169,9 @@ function scanA2uiTagsFromMessages(messages, processedTagIds) {
4075
4169
  }
4076
4170
  function reduceA2uiRuntimeMessages(state, messages) {
4077
4171
  const { shouldReplayAll, pendingItems, nextCursors } = diffConversationMessages(messages || [], state.processedMessageCursors);
4078
- const itemsToProcess = shouldReplayAll ? messages.flatMap((message3, messageIndex) => {
4079
- const messageId = String(message3?.messageId ?? messageIndex);
4080
- const items = Array.isArray(message3?.content) ? message3.content : [];
4081
- return items.map((item) => ({ messageIndex, messageId, item }));
4082
- }) : pendingItems;
4083
4172
  const tagProcessedSet = new Set(shouldReplayAll ? [] : state.processedTagIds);
4084
4173
  const { newTags, newTagIds } = scanA2uiTagsFromMessages(messages || [], tagProcessedSet);
4085
- if (!shouldReplayAll && itemsToProcess.length === 0 && newTags.length === 0) {
4174
+ if (!shouldReplayAll && pendingItems.length === 0 && newTags.length === 0) {
4086
4175
  return { state, effects: [] };
4087
4176
  }
4088
4177
  const nextState = shouldReplayAll ? createA2uiRuntimeState() : { ...state };
@@ -4101,7 +4190,7 @@ function reduceA2uiRuntimeMessages(state, messages) {
4101
4190
  const effects = shouldReplayAll ? [{ type: "reset-model-store" }] : [];
4102
4191
  const deletedSurfaceIds = /* @__PURE__ */ new Set();
4103
4192
  const nextWizardSteps = {};
4104
- itemsToProcess.forEach(({ item, messageIndex, messageId }) => {
4193
+ pendingItems.forEach(({ item, messageIndex, messageId }) => {
4105
4194
  if (item?.type === "a2uiSchema") {
4106
4195
  const schema = normalizeWizardSchema(item.schema);
4107
4196
  if (schema) {
@@ -4270,11 +4359,9 @@ var A2uiRuntimeContext = React10__default.createContext({
4270
4359
  function useA2uiRuntimeView() {
4271
4360
  return React10__default.useContext(A2uiRuntimeContext);
4272
4361
  }
4273
- function A2uiMessageCards({ messageIndex, message: message3 }) {
4362
+ function A2uiMessageCards({ messageIndex }) {
4274
4363
  const { surfaceIdsByMessageIndex } = useA2uiRuntimeView();
4275
- const allSurfaceIds = surfaceIdsByMessageIndex[messageIndex] || [];
4276
- const inlineSurfaceIds = message3 ? extractInlineSurfaceIdsFromMessage(message3) : /* @__PURE__ */ new Set();
4277
- const surfaceIds = allSurfaceIds.filter((id) => !inlineSurfaceIds.has(id));
4364
+ const surfaceIds = surfaceIdsByMessageIndex[messageIndex] || [];
4278
4365
  if (!surfaceIds.length) return null;
4279
4366
  return /* @__PURE__ */ jsx("div", { children: surfaceIds.map((surfaceId) => /* @__PURE__ */ jsx(XCard.Card, { id: surfaceId }, surfaceId)) });
4280
4367
  }
@@ -4480,16 +4567,14 @@ function buildLatestCommandIndexBySurface(messages) {
4480
4567
  if (surfaceId) indexBySurface[surfaceId] = commandIndex;
4481
4568
  continue;
4482
4569
  }
4483
- if (item?.type === "text") {
4484
- const text = item.messageContent || item.text || "";
4485
- if (typeof text !== "string" || !text.includes("<A2UI")) continue;
4486
- const tags = parseA2uiTagsFromText(text);
4487
- for (const tag of tags) {
4488
- for (const cmd of tag.commands) {
4489
- commandIndex += 1;
4490
- const surfaceId = extractSurfaceId3(cmd);
4491
- if (surfaceId) indexBySurface[surfaceId] = commandIndex;
4492
- }
4570
+ const text = extractItemTextForA2ui(item);
4571
+ if (typeof text !== "string" || !text.includes("<A2UI")) continue;
4572
+ const tags = parseA2uiTagsFromText(text);
4573
+ for (const tag of tags) {
4574
+ for (const cmd of tag.commands) {
4575
+ commandIndex += 1;
4576
+ const surfaceId = extractSurfaceId3(cmd);
4577
+ if (surfaceId) indexBySurface[surfaceId] = commandIndex;
4493
4578
  }
4494
4579
  }
4495
4580
  }
@@ -4593,7 +4678,8 @@ var FilesNode = React10__default.memo(({ item }) => {
4593
4678
 
4594
4679
  // src/components/CustomComponents/MessageNode/style.module.less
4595
4680
  var style_module_default2 = {
4596
- runStartedNode: "style_module_runStartedNode"};
4681
+ runStartedNode: "style_module_runStartedNode",
4682
+ dot: "style_module_dot"};
4597
4683
  var QuoteMsgNode = React10__default.memo(({ quoteMsg, role }) => {
4598
4684
  if (!quoteMsg || !quoteMsg.messageContent) return null;
4599
4685
  return /* @__PURE__ */ jsx(
@@ -4624,9 +4710,12 @@ var QuoteMsgNode = React10__default.memo(({ quoteMsg, role }) => {
4624
4710
  }
4625
4711
  );
4626
4712
  });
4627
- var RunStartedNode = React10__default.memo(({ loading }) => {
4628
- if (!loading) return null;
4629
- return /* @__PURE__ */ jsx(Flex, { gap: 8, align: "center", className: style_module_default2.runStartedNode, children: /* @__PURE__ */ jsx(LoadingOutlined, { style: { color: "#1677ff" } }) });
4713
+ var RunStartedNode = React10__default.memo(() => {
4714
+ return /* @__PURE__ */ jsxs("span", { className: style_module_default2.runStartedNode, children: [
4715
+ /* @__PURE__ */ jsx("span", { className: style_module_default2.dot }),
4716
+ /* @__PURE__ */ jsx("span", { className: style_module_default2.dot }),
4717
+ /* @__PURE__ */ jsx("span", { className: style_module_default2.dot })
4718
+ ] });
4630
4719
  });
4631
4720
  var RESOURCE_MARKDOWN_TAG = "resourcetag";
4632
4721
  var RESOURCE_TOKEN_REGEX = /(\w+):\/\/([^?\s]+)\?name=([^&\s]+)&label=([^\s]+)/g;
@@ -4658,39 +4747,20 @@ var TextNode2 = React10__default.memo(
4658
4747
  item,
4659
4748
  role,
4660
4749
  customComponents,
4661
- message: message3,
4662
- messageIndex = -1
4750
+ message: message3
4663
4751
  }) => {
4664
- const { surfaceIdsByMessageIndex } = useA2uiRuntimeView();
4665
- const rawContent = toA2uiDisplayText(role, item?.messageContent);
4666
- const segments = splitA2uiTextSegments(rawContent);
4752
+ const content = toA2uiDisplayText(role, item?.messageContent);
4667
4753
  const markdownComponents = {
4668
4754
  [RESOURCE_MARKDOWN_TAG]: MessageResourceTag,
4669
4755
  ...customComponents
4670
4756
  };
4671
- const visibleSurfaceIds = messageIndex >= 0 ? new Set(surfaceIdsByMessageIndex[messageIndex] || []) : null;
4672
- const firstSeg = segments[0];
4673
- const isPureText = segments.length === 0 || segments.length === 1 && firstSeg.type === "text";
4674
- if (isPureText) {
4675
- const content = firstSeg && firstSeg.type === "text" ? firstSeg.content : "";
4676
- if (typeof content === "string" && content.startsWith("Question:")) {
4677
- return /* @__PURE__ */ jsx(QuestionSummary, { content });
4678
- }
4679
- const markdownContent = typeof content === "string" ? transformResourceText(content) : content;
4680
- return /* @__PURE__ */ jsxs(Fragment, { children: [
4681
- !!item.reasoningContent && /* @__PURE__ */ jsx(Think, { title: "\u6DF1\u5EA6\u601D\u8003", children: item.reasoningContent }),
4682
- !!markdownContent && /* @__PURE__ */ jsx(XMarkdown_default, { message: message3, components: markdownComponents, content: markdownContent })
4683
- ] });
4757
+ if (typeof content === "string" && content.startsWith("Question:")) {
4758
+ return /* @__PURE__ */ jsx(QuestionSummary, { content });
4684
4759
  }
4760
+ const markdownContent = typeof content === "string" ? transformResourceText(content) : content;
4685
4761
  return /* @__PURE__ */ jsxs(Fragment, { children: [
4686
4762
  !!item.reasoningContent && /* @__PURE__ */ jsx(Think, { title: "\u6DF1\u5EA6\u601D\u8003", children: item.reasoningContent }),
4687
- segments.map((seg, i) => {
4688
- if (seg.type === "text") {
4689
- const markdownContent = transformResourceText(seg.content);
4690
- return seg.content.trim() ? /* @__PURE__ */ jsx(XMarkdown_default, { message: message3, components: markdownComponents, content: markdownContent }, `text-${i}`) : null;
4691
- }
4692
- return seg.surfaceIds.filter((sid) => !visibleSurfaceIds || visibleSurfaceIds.has(sid)).map((sid) => /* @__PURE__ */ jsx(XCard.Card, { id: sid }, `a2ui-${i}-${sid}`));
4693
- })
4763
+ !!markdownContent && /* @__PURE__ */ jsx(XMarkdown_default, { message: message3, components: markdownComponents, content: markdownContent })
4694
4764
  ] });
4695
4765
  }
4696
4766
  );
@@ -4699,11 +4769,17 @@ var TextNode2 = React10__default.memo(
4699
4769
  var index_module_default2 = {
4700
4770
  iconContainer: "index_module_iconContainer",
4701
4771
  toolName: "index_module_toolName",
4772
+ toolNamePending: "index_module_toolNamePending",
4773
+ dot: "index_module_dot",
4702
4774
  duration: "index_module_duration",
4703
4775
  statusIcon: "index_module_statusIcon",
4776
+ expandIcon: "index_module_expandIcon",
4777
+ expanded: "index_module_expanded",
4704
4778
  sectionLabel: "index_module_sectionLabel",
4779
+ plainTextContainer: "index_module_plainTextContainer",
4705
4780
  markdownContainer: "index_module_markdownContainer",
4706
4781
  sectionBlock: "index_module_sectionBlock",
4782
+ contentScrollContainer: "index_module_contentScrollContainer",
4707
4783
  todoList: "index_module_todoList",
4708
4784
  todoItem: "index_module_todoItem",
4709
4785
  statusIconWrapper: "index_module_statusIconWrapper",
@@ -4713,6 +4789,9 @@ var index_module_default2 = {
4713
4789
  emptyText: "index_module_emptyText"
4714
4790
  };
4715
4791
  var DefaultToolRender = ({ argsContent, resultContent, errorMessage, item }) => {
4792
+ if (item.display) {
4793
+ return /* @__PURE__ */ jsx("pre", { className: index_module_default2.plainTextContainer, children: item.display });
4794
+ }
4716
4795
  return /* @__PURE__ */ jsxs(Fragment, { children: [
4717
4796
  (item.content || item.arguments) && argsContent && /* @__PURE__ */ jsxs("div", { className: index_module_default2.sectionBlock, children: [
4718
4797
  /* @__PURE__ */ jsx(Typography.Text, { className: index_module_default2.sectionLabel, children: "\u8F93\u5165\u53C2\u6570" }),
@@ -4788,6 +4867,15 @@ var getToolRenderConfig = (toolName) => {
4788
4867
  alwaysShowContent: false
4789
4868
  };
4790
4869
  };
4870
+ function stripA2uiTagsFromResult(result) {
4871
+ if (!result || typeof result !== "object" || Array.isArray(result)) return result;
4872
+ const cleaned = {};
4873
+ for (const [key, value] of Object.entries(result)) {
4874
+ cleaned[key] = typeof value === "string" && value.includes("<A2UI") ? stripA2uiTags(value) : value;
4875
+ }
4876
+ const hasVisible = Object.values(cleaned).some((v) => v !== "" && v !== null && v !== void 0);
4877
+ return hasVisible ? cleaned : null;
4878
+ }
4791
4879
  var formatContent = (content) => {
4792
4880
  try {
4793
4881
  if (!content) return { text: "", isJson: false, parsed: null };
@@ -4798,14 +4886,16 @@ var formatContent = (content) => {
4798
4886
  if (typeof parsed === "object" && parsed !== null) {
4799
4887
  return { text: JSON.stringify(parsed, null, 2), isJson: true, parsed };
4800
4888
  }
4801
- return { text: content, isJson: false, parsed: null };
4889
+ const stripped = content.includes("<A2UI") ? stripA2uiTags(content) : content;
4890
+ return { text: stripped, isJson: false, parsed: null };
4802
4891
  } catch {
4803
- return { text: typeof content === "string" ? content : "", isJson: false, parsed: null };
4892
+ const text = typeof content === "string" ? content.includes("<A2UI") ? stripA2uiTags(content) : content : "";
4893
+ return { text, isJson: false, parsed: null };
4804
4894
  }
4805
4895
  };
4806
4896
  var ToolCallItem = ({ item }) => {
4807
4897
  const { token } = theme.useToken();
4808
- const renderConfig = getToolRenderConfig(item.toolName);
4898
+ const renderConfig = getToolRenderConfig(item);
4809
4899
  const CustomRender = renderConfig.component;
4810
4900
  const status = useMemo(() => {
4811
4901
  if (item.status) return item.status;
@@ -4814,7 +4904,12 @@ var ToolCallItem = ({ item }) => {
4814
4904
  return "running";
4815
4905
  }, [item.status, item.errorMessage, item.result]);
4816
4906
  const argsContent = useMemo(() => formatContent(item.arguments || item.content), [item.arguments, item.content]);
4817
- const resultContent = useMemo(() => item.result ? formatContent(item.result) : null, [item.result]);
4907
+ const resultContent = useMemo(() => {
4908
+ if (!item.result) return null;
4909
+ const cleanedResult = stripA2uiTagsFromResult(item.result);
4910
+ if (!cleanedResult) return null;
4911
+ return formatContent(cleanedResult);
4912
+ }, [item.result]);
4818
4913
  const hasContent = useMemo(() => {
4819
4914
  if (renderConfig.disableExpandOnError && status === "error") return false;
4820
4915
  let alwaysShow = false;
@@ -4824,35 +4919,30 @@ var ToolCallItem = ({ item }) => {
4824
4919
  alwaysShow = renderConfig.alwaysShowContent;
4825
4920
  }
4826
4921
  if (alwaysShow) return true;
4827
- return Boolean(item.errorMessage);
4828
- }, [renderConfig.disableExpandOnError, renderConfig.alwaysShowContent, item.errorMessage, status, argsContent.parsed, resultContent?.parsed]);
4922
+ if (item.display) return true;
4923
+ if (item.errorMessage) return true;
4924
+ if (argsContent.text) return true;
4925
+ if (resultContent?.text) return true;
4926
+ return false;
4927
+ }, [
4928
+ renderConfig.disableExpandOnError,
4929
+ renderConfig.alwaysShowContent,
4930
+ item.display,
4931
+ item.errorMessage,
4932
+ status,
4933
+ argsContent.parsed,
4934
+ resultContent?.parsed,
4935
+ argsContent.text,
4936
+ resultContent?.text
4937
+ ]);
4829
4938
  const isDefaultExpanded = useMemo(() => {
4830
4939
  if (typeof renderConfig.defaultExpanded === "function") {
4831
4940
  return renderConfig.defaultExpanded(argsContent.parsed, resultContent?.parsed);
4832
4941
  }
4833
4942
  return renderConfig.defaultExpanded;
4834
4943
  }, [renderConfig.defaultExpanded, argsContent.parsed, resultContent?.parsed]);
4835
- const statusConfig = {
4836
- running: {
4837
- icon: /* @__PURE__ */ jsx(LoadingOutlined, {}),
4838
- color: token.colorPrimary
4839
- },
4840
- success: {
4841
- icon: null,
4842
- color: token.colorSuccess
4843
- },
4844
- error: {
4845
- icon: null,
4846
- color: token.colorSuccess
4847
- },
4848
- pending: {
4849
- icon: /* @__PURE__ */ jsx(LoadingOutlined, {}),
4850
- color: token.colorTextSecondary
4851
- }
4852
- }[status] || {
4853
- icon: /* @__PURE__ */ jsx(LoadingOutlined, {}),
4854
- color: token.colorPrimary
4855
- };
4944
+ const showLoading = status === "running" || status === "pending";
4945
+ const displayName = item.title || (showLoading ? "" : item.toolName || "Unknown Tool");
4856
4946
  const renderIcon = () => {
4857
4947
  if (!item.toolIcon) {
4858
4948
  return /* @__PURE__ */ jsx(ToolOutlined, { style: { fontSize: 14, color: token.colorTextSecondary } });
@@ -4870,9 +4960,11 @@ var ToolCallItem = ({ item }) => {
4870
4960
  collapsible: hasContent ? void 0 : "disabled",
4871
4961
  defaultActiveKey: isDefaultExpanded && hasContent ? [item.toolCallId || "fallback-key"] : void 0,
4872
4962
  expandIconPlacement: "end",
4963
+ expandIcon: ({ isActive }) => hasContent ? /* @__PURE__ */ jsx(RightOutlined, { className: `${index_module_default2.expandIcon} ${isActive ? index_module_default2.expanded : ""}` }) : null,
4873
4964
  styles: {
4874
4965
  header: {
4875
- padding: "6px 10px"
4966
+ padding: "6px 10px",
4967
+ overflow: "hidden"
4876
4968
  }
4877
4969
  },
4878
4970
  items: [
@@ -4881,14 +4973,18 @@ var ToolCallItem = ({ item }) => {
4881
4973
  showArrow: hasContent,
4882
4974
  label: /* @__PURE__ */ jsxs(Flex, { align: "center", gap: 8, style: { flex: 1, minWidth: 0 }, children: [
4883
4975
  /* @__PURE__ */ jsx("div", { className: index_module_default2.iconContainer, children: renderIcon() }),
4884
- /* @__PURE__ */ jsx("span", { className: index_module_default2.toolName, children: item.title || item.toolName || "Unknown Tool" }),
4885
- (status === "running" || status === "pending") && /* @__PURE__ */ jsx("div", { className: index_module_default2.statusIcon, style: { color: statusConfig.color }, children: statusConfig.icon }),
4976
+ displayName ? /* @__PURE__ */ jsx("span", { className: index_module_default2.toolName, children: displayName }) : /* @__PURE__ */ jsxs("span", { className: index_module_default2.toolNamePending, children: [
4977
+ /* @__PURE__ */ jsx("span", { className: index_module_default2.dot }),
4978
+ /* @__PURE__ */ jsx("span", { className: index_module_default2.dot }),
4979
+ /* @__PURE__ */ jsx("span", { className: index_module_default2.dot })
4980
+ ] }),
4981
+ showLoading && /* @__PURE__ */ jsx("div", { className: index_module_default2.statusIcon, style: { color: token.colorPrimary }, children: /* @__PURE__ */ jsx(LoadingOutlined, {}) }),
4886
4982
  item.duration && /* @__PURE__ */ jsxs(Typography.Text, { className: index_module_default2.duration, children: [
4887
4983
  item.duration,
4888
4984
  "ms"
4889
4985
  ] })
4890
4986
  ] }),
4891
- children: /* @__PURE__ */ jsx(
4987
+ children: /* @__PURE__ */ jsx("div", { className: index_module_default2.contentScrollContainer, children: /* @__PURE__ */ jsx(
4892
4988
  CustomRender,
4893
4989
  {
4894
4990
  item,
@@ -4898,35 +4994,30 @@ var ToolCallItem = ({ item }) => {
4898
4994
  resultContent,
4899
4995
  errorMessage: item.errorMessage
4900
4996
  }
4901
- )
4997
+ ) })
4902
4998
  }
4903
4999
  ]
4904
5000
  }
4905
5001
  );
4906
5002
  };
4907
5003
  var tool_call_item_default = ToolCallItem;
4908
- var RENDERABLE_MESSAGE_TYPES = ["runStarted", "toolCall", "toolResult", "text", "stepError", "files", "plan"];
5004
+ var RENDERABLE_MESSAGE_TYPES = ["runStarted", "toolCall", "toolResult", "text", "stepError", "runFailed", "files", "plan"];
4909
5005
  var MessageRender_default = React10__default.memo(({ role, message: message3, messageIndex = -1, loading, containerRef, customComponents }) => {
4910
5006
  const content = useMemo(() => {
4911
5007
  return (message3.content || []).filter((item) => {
4912
5008
  if (!RENDERABLE_MESSAGE_TYPES.includes(item.type)) {
4913
5009
  return false;
4914
5010
  }
4915
- if (item.type === "runStarted") {
4916
- return !!loading;
4917
- }
4918
5011
  if (item.type === "plan") {
4919
5012
  return !shouldHideA2uiPlan(item);
4920
5013
  }
4921
5014
  if (item.type === "text") {
4922
5015
  const rawText = item.messageContent || item.text || "";
4923
- const visibleText = stripA2uiTags(rawText);
4924
- const hasA2uiTag2 = typeof rawText === "string" && rawText.includes("<A2UI");
4925
- return !!visibleText.trim() || !!item.reasoningContent || hasA2uiTag2;
5016
+ return !!rawText.trim() || !!item.reasoningContent;
4926
5017
  }
4927
5018
  return true;
4928
5019
  });
4929
- }, [loading, message3.content]);
5020
+ }, [message3.content]);
4930
5021
  const quoteMsg = useMemo(() => {
4931
5022
  const quoteMsg2 = {};
4932
5023
  if (message3.params) {
@@ -4940,29 +5031,46 @@ var MessageRender_default = React10__default.memo(({ role, message: message3, me
4940
5031
  }
4941
5032
  return isEmptyObj(quoteMsg2) ? null : quoteMsg2;
4942
5033
  }, [message3.params, message3.quoteMsg]);
4943
- if (content.length === 0) return null;
5034
+ const showPending = loading && (content.length === 0 || content[content.length - 1].type !== "text");
5035
+ if (content.length === 0 && !showPending) return null;
5036
+ const lastToolCallIndex = (() => {
5037
+ let lastIdx = -1;
5038
+ content.forEach((item, i) => {
5039
+ if (item.type === "toolCall" || item.type === "toolResult") lastIdx = i;
5040
+ });
5041
+ return lastIdx;
5042
+ })();
4944
5043
  return /* @__PURE__ */ jsxs(Flex, { ref: containerRef, vertical: true, gap: 8, children: [
4945
- content.map((item, index) => {
4946
- return /* @__PURE__ */ jsx(
5044
+ content.map((item, index) => /* @__PURE__ */ jsxs(React10__default.Fragment, { children: [
5045
+ /* @__PURE__ */ jsx(
4947
5046
  Bubble,
4948
5047
  {
4949
5048
  role: role.user,
4950
5049
  placement: role.placement,
4951
5050
  variant: item.type === "files" ? "borderless" : void 0,
4952
5051
  content: /* @__PURE__ */ jsxs(Fragment, { children: [
4953
- item.type === "runStarted" && /* @__PURE__ */ jsx(RunStartedNode, { loading }, `flow-start-${index}`),
4954
5052
  (item.type === "toolCall" || item.type === "toolResult") && /* @__PURE__ */ jsx(tool_call_item_default, { item }, `tool-call-${item.toolCallId || index}`),
4955
- item.type === "text" && /* @__PURE__ */ jsx(TextNode2, { item, role: message3.role, customComponents, message: message3, messageIndex }, `message-${index}`),
4956
- item.type === "stepError" && (item.errorMessage ? /* @__PURE__ */ jsx(XMarkdown_default, { message: message3, components: customComponents, content: item.errorMessage }) : null),
5053
+ item.type === "text" && /* @__PURE__ */ jsx(
5054
+ TextNode2,
5055
+ {
5056
+ item,
5057
+ role: message3.role,
5058
+ customComponents,
5059
+ message: message3,
5060
+ messageIndex
5061
+ },
5062
+ `message-${index}`
5063
+ ),
5064
+ (item.type === "stepError" || item.type === "runFailed") && (item.errorMessage ? /* @__PURE__ */ jsx(XMarkdown_default, { message: message3, components: customComponents, content: item.errorMessage }) : null),
4957
5065
  item.type === "files" && /* @__PURE__ */ jsx(FilesNode, { item }, `files-${index}`),
4958
5066
  item.type === "plan" && /* @__PURE__ */ jsx(A2uiPlanNode, { item }, `plan-${index}`)
4959
5067
  ] })
4960
- },
4961
- `message-${index}`
4962
- );
4963
- }),
4964
- quoteMsg && /* @__PURE__ */ jsx(QuoteMsgNode, { quoteMsg, role }),
4965
- messageIndex >= 0 ? /* @__PURE__ */ jsx(A2uiMessageCards, { messageIndex, message: message3 }) : null
5068
+ }
5069
+ ),
5070
+ index === lastToolCallIndex && messageIndex >= 0 ? /* @__PURE__ */ jsx(A2uiMessageCards, { messageIndex, message: message3 }) : null
5071
+ ] }, `message-${index}`)),
5072
+ showPending && /* @__PURE__ */ jsx(Bubble, { role: role.user, placement: role.placement, content: /* @__PURE__ */ jsx(RunStartedNode, {}) }),
5073
+ quoteMsg && /* @__PURE__ */ jsx(QuoteMsgNode, { quoteMsg, role })
4966
5074
  ] });
4967
5075
  });
4968
5076
  var WelcomeItem_default = ({ icon = true, title = true, description = true, prompts = true }) => {