@blade-hq/agent-react 2610.0.0-beta.0 → 2610.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/dist/components/AgentChat.d.ts +3 -0
- package/dist/components/AssistantTurnBlock.d.ts +1 -1
- package/dist/components/ChatSurface.d.ts +11 -2
- package/dist/components/ChatView.d.ts +1 -0
- package/dist/components/MarkdownContent.d.ts +3 -6
- package/dist/components/MessageList.d.ts +10 -3
- package/dist/components/PostChatFollowupBlock.d.ts +59 -0
- package/dist/embed/entry.d.ts +2 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +636 -312
- package/dist/index.js.map +1 -1
- package/dist/style.full.css +1 -1
- package/package.json +5 -3
- package/public-api.md +145 -1
- package/dist/components/FileCard.d.ts +0 -16
- package/dist/lib/media-tags.d.ts +0 -24
package/dist/index.js
CHANGED
|
@@ -545,7 +545,7 @@ function toToolCallInfo(call, results, failedToolIds) {
|
|
|
545
545
|
}
|
|
546
546
|
|
|
547
547
|
// src/components/AgentChat.tsx
|
|
548
|
-
import { BladeApiError } from "@blade-hq/agent-client";
|
|
548
|
+
import { BladeApiError, latestPostChatFollowup } from "@blade-hq/agent-client";
|
|
549
549
|
|
|
550
550
|
// ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/createLucideIcon.js
|
|
551
551
|
import { forwardRef as forwardRef2, createElement as createElement2 } from "react";
|
|
@@ -618,11 +618,16 @@ var createLucideIcon = (iconName, iconNode) => {
|
|
|
618
618
|
return Component2;
|
|
619
619
|
};
|
|
620
620
|
|
|
621
|
-
// ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/
|
|
622
|
-
var
|
|
623
|
-
["
|
|
624
|
-
["path", { d: "
|
|
625
|
-
|
|
621
|
+
// ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/arrow-right.js
|
|
622
|
+
var ArrowRight = createLucideIcon("ArrowRight", [
|
|
623
|
+
["path", { d: "M5 12h14", key: "1ays0h" }],
|
|
624
|
+
["path", { d: "m12 5 7 7-7 7", key: "xquz4c" }]
|
|
625
|
+
]);
|
|
626
|
+
|
|
627
|
+
// ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/arrow-up-right.js
|
|
628
|
+
var ArrowUpRight = createLucideIcon("ArrowUpRight", [
|
|
629
|
+
["path", { d: "M7 7h10v10", key: "1tivn9" }],
|
|
630
|
+
["path", { d: "M7 17 17 7", key: "1vkiza" }]
|
|
626
631
|
]);
|
|
627
632
|
|
|
628
633
|
// ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/arrow-up.js
|
|
@@ -699,24 +704,6 @@ var Download = createLucideIcon("Download", [
|
|
|
699
704
|
["line", { x1: "12", x2: "12", y1: "15", y2: "3", key: "1vk2je" }]
|
|
700
705
|
]);
|
|
701
706
|
|
|
702
|
-
// ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/file-code-2.js
|
|
703
|
-
var FileCode2 = createLucideIcon("FileCode2", [
|
|
704
|
-
["path", { d: "M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4", key: "1pf5j1" }],
|
|
705
|
-
["path", { d: "M14 2v4a2 2 0 0 0 2 2h4", key: "tnqrlb" }],
|
|
706
|
-
["path", { d: "m5 12-3 3 3 3", key: "oke12k" }],
|
|
707
|
-
["path", { d: "m9 18 3-3-3-3", key: "112psh" }]
|
|
708
|
-
]);
|
|
709
|
-
|
|
710
|
-
// ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/file-spreadsheet.js
|
|
711
|
-
var FileSpreadsheet = createLucideIcon("FileSpreadsheet", [
|
|
712
|
-
["path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z", key: "1rqfz7" }],
|
|
713
|
-
["path", { d: "M14 2v4a2 2 0 0 0 2 2h4", key: "tnqrlb" }],
|
|
714
|
-
["path", { d: "M8 13h2", key: "yr2amv" }],
|
|
715
|
-
["path", { d: "M14 13h2", key: "un5t4a" }],
|
|
716
|
-
["path", { d: "M8 17h2", key: "2yhykz" }],
|
|
717
|
-
["path", { d: "M14 17h2", key: "10kma7" }]
|
|
718
|
-
]);
|
|
719
|
-
|
|
720
707
|
// ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/file-text.js
|
|
721
708
|
var FileText = createLucideIcon("FileText", [
|
|
722
709
|
["path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z", key: "1rqfz7" }],
|
|
@@ -744,11 +731,11 @@ var Film = createLucideIcon("Film", [
|
|
|
744
731
|
["path", { d: "M17 16.5h4", key: "go4c1d" }]
|
|
745
732
|
]);
|
|
746
733
|
|
|
747
|
-
// ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/
|
|
748
|
-
var
|
|
749
|
-
["
|
|
750
|
-
["
|
|
751
|
-
["path", { d: "
|
|
734
|
+
// ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/globe.js
|
|
735
|
+
var Globe = createLucideIcon("Globe", [
|
|
736
|
+
["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
|
|
737
|
+
["path", { d: "M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20", key: "13o1zl" }],
|
|
738
|
+
["path", { d: "M2 12h20", key: "9i4pu4" }]
|
|
752
739
|
]);
|
|
753
740
|
|
|
754
741
|
// ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/layers.js
|
|
@@ -814,13 +801,6 @@ var MessageSquare = createLucideIcon("MessageSquare", [
|
|
|
814
801
|
["path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z", key: "1lielz" }]
|
|
815
802
|
]);
|
|
816
803
|
|
|
817
|
-
// ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/music.js
|
|
818
|
-
var Music = createLucideIcon("Music", [
|
|
819
|
-
["path", { d: "M9 18V5l12-2v13", key: "1jmyc2" }],
|
|
820
|
-
["circle", { cx: "6", cy: "18", r: "3", key: "fqmcym" }],
|
|
821
|
-
["circle", { cx: "18", cy: "16", r: "3", key: "1hluhg" }]
|
|
822
|
-
]);
|
|
823
|
-
|
|
824
804
|
// ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/play.js
|
|
825
805
|
var Play = createLucideIcon("Play", [
|
|
826
806
|
["polygon", { points: "6 3 20 12 6 21 6 3", key: "1oa8hb" }]
|
|
@@ -834,6 +814,21 @@ var Settings2 = createLucideIcon("Settings2", [
|
|
|
834
814
|
["circle", { cx: "7", cy: "7", r: "3", key: "dfmy0x" }]
|
|
835
815
|
]);
|
|
836
816
|
|
|
817
|
+
// ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/sparkles.js
|
|
818
|
+
var Sparkles = createLucideIcon("Sparkles", [
|
|
819
|
+
[
|
|
820
|
+
"path",
|
|
821
|
+
{
|
|
822
|
+
d: "M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z",
|
|
823
|
+
key: "4pj2yx"
|
|
824
|
+
}
|
|
825
|
+
],
|
|
826
|
+
["path", { d: "M20 3v4", key: "1olli1" }],
|
|
827
|
+
["path", { d: "M22 5h-4", key: "1gvqau" }],
|
|
828
|
+
["path", { d: "M4 17v2", key: "vumght" }],
|
|
829
|
+
["path", { d: "M5 18H3", key: "zchphs" }]
|
|
830
|
+
]);
|
|
831
|
+
|
|
837
832
|
// ../../node_modules/.pnpm/lucide-react@0.468.0_react@19.2.4/node_modules/lucide-react/dist/esm/icons/square.js
|
|
838
833
|
var Square = createLucideIcon("Square", [
|
|
839
834
|
["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", key: "afitv7" }]
|
|
@@ -859,7 +854,7 @@ var X = createLucideIcon("X", [
|
|
|
859
854
|
]);
|
|
860
855
|
|
|
861
856
|
// src/components/AgentChat.tsx
|
|
862
|
-
import { useEffect as
|
|
857
|
+
import { useCallback as useCallback7, useEffect as useEffect8, useMemo as useMemo8, useState as useState12 } from "react";
|
|
863
858
|
|
|
864
859
|
// src/lib/utils.ts
|
|
865
860
|
function cn(...inputs) {
|
|
@@ -1083,7 +1078,7 @@ function ConnectionBanner({ connection, className }) {
|
|
|
1083
1078
|
|
|
1084
1079
|
// src/components/MessageList.tsx
|
|
1085
1080
|
import { isHiddenInternalMessage } from "@blade-hq/agent-client";
|
|
1086
|
-
import { useCallback as
|
|
1081
|
+
import { useCallback as useCallback6, useEffect as useEffect7, useMemo as useMemo7, useRef as useRef7, useState as useState11 } from "react";
|
|
1087
1082
|
|
|
1088
1083
|
// ../../node_modules/.pnpm/use-stick-to-bottom@1.1.3_react@19.2.4/node_modules/use-stick-to-bottom/dist/useStickToBottom.js
|
|
1089
1084
|
import { useCallback as useCallback3, useMemo as useMemo3, useRef as useRef3, useState as useState4 } from "react";
|
|
@@ -1511,7 +1506,7 @@ function useStickToBottomContext() {
|
|
|
1511
1506
|
|
|
1512
1507
|
// src/components/AssistantTurnBlock.tsx
|
|
1513
1508
|
import { getTextContent, normalizeMessageContent } from "@blade-hq/agent-client";
|
|
1514
|
-
import { useState as
|
|
1509
|
+
import { useState as useState9 } from "react";
|
|
1515
1510
|
|
|
1516
1511
|
// src/components/AgentLoopBlock.tsx
|
|
1517
1512
|
import { useState as useState5 } from "react";
|
|
@@ -1714,142 +1709,14 @@ import {
|
|
|
1714
1709
|
useEffect as useEffect4,
|
|
1715
1710
|
useMemo as useMemo5,
|
|
1716
1711
|
useRef as useRef5,
|
|
1717
|
-
useState as
|
|
1712
|
+
useState as useState6
|
|
1718
1713
|
} from "react";
|
|
1719
|
-
|
|
1720
|
-
// src/lib/media-tags.ts
|
|
1721
|
-
var FILE_CARD_TAG = "blade-file-card";
|
|
1722
|
-
var MEDIA_LINE_RE = /^[ \t]*(?:[-*+][ \t]+|\d+\.[ \t]+)?(?<wrap>[`"'*_]*)MEDIA:[ \t]*(?<path>.+?)\k<wrap>[ \t]*[。,、;;,]?[ \t]*\r?$/gm;
|
|
1723
|
-
var MEDIA_LINE_START_RE = /^[ \t]*(?:[-*+][ \t]+|\d+\.[ \t]+)?[`"'*_]*MEDIA:/;
|
|
1724
|
-
function basename(path) {
|
|
1725
|
-
return path.split(/[/\\]/).filter(Boolean).pop() || path;
|
|
1726
|
-
}
|
|
1727
|
-
function unwrapMediaPath(path) {
|
|
1728
|
-
if (!path.startsWith("<")) return path;
|
|
1729
|
-
const closingBracket = path.indexOf(">");
|
|
1730
|
-
if (closingBracket < 0) return null;
|
|
1731
|
-
return `${path.slice(1, closingBracket)}${path.slice(closingBracket + 1)}`;
|
|
1732
|
-
}
|
|
1733
|
-
function isSafeMediaPath(path) {
|
|
1734
|
-
if (!path) return false;
|
|
1735
|
-
return !path.split(/[/\\]/).includes("..");
|
|
1736
|
-
}
|
|
1737
|
-
function escapeAttribute(value) {
|
|
1738
|
-
return value.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
1739
|
-
}
|
|
1740
|
-
function foldMediaLines(text) {
|
|
1741
|
-
return text.replace(MEDIA_LINE_RE, (match, _wrap, rawPath) => {
|
|
1742
|
-
const path = unwrapMediaPath(rawPath);
|
|
1743
|
-
if (path === null) return match;
|
|
1744
|
-
const name = basename(path);
|
|
1745
|
-
if (!isSafeMediaPath(path)) {
|
|
1746
|
-
return `\`${name}\``;
|
|
1747
|
-
}
|
|
1748
|
-
return `<${FILE_CARD_TAG} data-path="${escapeAttribute(path)}" data-name="${escapeAttribute(name)}">${escapeAttribute(name)}</${FILE_CARD_TAG}>`;
|
|
1749
|
-
});
|
|
1750
|
-
}
|
|
1751
|
-
function collapseMediaTags(text, options) {
|
|
1752
|
-
if (!text.includes("MEDIA:")) return text;
|
|
1753
|
-
if (!options?.streaming) return foldMediaLines(text);
|
|
1754
|
-
const newlineIndex = text.lastIndexOf("\n");
|
|
1755
|
-
const head = newlineIndex < 0 ? "" : text.slice(0, newlineIndex + 1);
|
|
1756
|
-
const lastLine = newlineIndex < 0 ? text : text.slice(newlineIndex + 1);
|
|
1757
|
-
if (MEDIA_LINE_START_RE.test(lastLine)) {
|
|
1758
|
-
return foldMediaLines(head);
|
|
1759
|
-
}
|
|
1760
|
-
return foldMediaLines(head) + lastLine;
|
|
1761
|
-
}
|
|
1762
|
-
|
|
1763
|
-
// src/components/FileCard.tsx
|
|
1764
|
-
import { useState as useState6 } from "react";
|
|
1765
1714
|
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1766
|
-
var IMAGE_EXTS = /* @__PURE__ */ new Set(["png", "jpg", "jpeg", "gif", "svg", "webp", "ico", "bmp"]);
|
|
1767
|
-
var SHEET_EXTS = /* @__PURE__ */ new Set(["xlsx", "xls", "xlsm", "xlsb", "csv"]);
|
|
1768
|
-
var TEXT_EXTS = /* @__PURE__ */ new Set(["txt", "md", "markdown", "pdf", "doc", "docx", "rtf"]);
|
|
1769
|
-
var CODE_EXTS = /* @__PURE__ */ new Set(["js", "jsx", "ts", "tsx", "py", "go", "json", "yaml", "yml", "html", "css"]);
|
|
1770
|
-
var VIDEO_EXTS = /* @__PURE__ */ new Set(["mp4", "webm", "mov", "mkv", "avi"]);
|
|
1771
|
-
var AUDIO_EXTS = /* @__PURE__ */ new Set(["mp3", "wav", "ogg", "m4a", "flac"]);
|
|
1772
|
-
var ARCHIVE_EXTS = /* @__PURE__ */ new Set(["zip", "tar", "gz", "tgz", "rar", "7z"]);
|
|
1773
|
-
function getFileIcon(name) {
|
|
1774
|
-
const ext = name.split(".").pop()?.toLowerCase() ?? "";
|
|
1775
|
-
if (IMAGE_EXTS.has(ext)) return Image;
|
|
1776
|
-
if (SHEET_EXTS.has(ext)) return FileSpreadsheet;
|
|
1777
|
-
if (TEXT_EXTS.has(ext)) return FileText;
|
|
1778
|
-
if (CODE_EXTS.has(ext)) return FileCode2;
|
|
1779
|
-
if (VIDEO_EXTS.has(ext)) return Film;
|
|
1780
|
-
if (AUDIO_EXTS.has(ext)) return Music;
|
|
1781
|
-
if (ARCHIVE_EXTS.has(ext)) return Archive;
|
|
1782
|
-
return File;
|
|
1783
|
-
}
|
|
1784
|
-
function stringValue(value) {
|
|
1785
|
-
return typeof value === "string" ? value : void 0;
|
|
1786
|
-
}
|
|
1787
|
-
function extractChildrenText(children) {
|
|
1788
|
-
if (typeof children === "string") return children;
|
|
1789
|
-
if (Array.isArray(children)) return children.map(extractChildrenText).join("");
|
|
1790
|
-
if (children && typeof children === "object" && "props" in children) {
|
|
1791
|
-
return extractChildrenText(children.props?.children);
|
|
1792
|
-
}
|
|
1793
|
-
return "";
|
|
1794
|
-
}
|
|
1795
|
-
function FileCard({
|
|
1796
|
-
node,
|
|
1797
|
-
"data-path": pathAttribute,
|
|
1798
|
-
"data-name": nameAttribute,
|
|
1799
|
-
dataPath,
|
|
1800
|
-
dataName,
|
|
1801
|
-
sessionId,
|
|
1802
|
-
children,
|
|
1803
|
-
className,
|
|
1804
|
-
...props
|
|
1805
|
-
}) {
|
|
1806
|
-
const client = useBladeClient();
|
|
1807
|
-
const [downloading, setDownloading] = useState6(false);
|
|
1808
|
-
const [failed, setFailed] = useState6(false);
|
|
1809
|
-
const nodeProperties = node && typeof node === "object" && "properties" in node ? node.properties : void 0;
|
|
1810
|
-
const path = pathAttribute ?? dataPath ?? stringValue(nodeProperties?.["data-path"]) ?? stringValue(nodeProperties?.dataPath) ?? "";
|
|
1811
|
-
const name = nameAttribute ?? dataName ?? stringValue(nodeProperties?.["data-name"]) ?? stringValue(nodeProperties?.dataName) ?? extractChildrenText(children) ?? "";
|
|
1812
|
-
const disabled = !sessionId || !isSafeMediaPath(path);
|
|
1813
|
-
const Icon2 = getFileIcon(name);
|
|
1814
|
-
const handleDownload = async () => {
|
|
1815
|
-
if (disabled || downloading || !sessionId) return;
|
|
1816
|
-
setDownloading(true);
|
|
1817
|
-
setFailed(false);
|
|
1818
|
-
try {
|
|
1819
|
-
await client.sessions.downloadFile(sessionId, path, name);
|
|
1820
|
-
} catch {
|
|
1821
|
-
setFailed(true);
|
|
1822
|
-
} finally {
|
|
1823
|
-
setDownloading(false);
|
|
1824
|
-
}
|
|
1825
|
-
};
|
|
1826
|
-
return /* @__PURE__ */ jsxs6("span", { ...props, className: cn("blade-chat-file-card", className), children: [
|
|
1827
|
-
/* @__PURE__ */ jsxs6(
|
|
1828
|
-
"button",
|
|
1829
|
-
{
|
|
1830
|
-
type: "button",
|
|
1831
|
-
onClick: handleDownload,
|
|
1832
|
-
disabled: disabled || downloading,
|
|
1833
|
-
"aria-label": `\u4E0B\u8F7D\u6587\u4EF6\uFF1A${name}`,
|
|
1834
|
-
title: failed ? "\u4E0B\u8F7D\u5931\u8D25\uFF0C\u70B9\u51FB\u91CD\u8BD5" : `\u4E0B\u8F7D ${name}`,
|
|
1835
|
-
children: [
|
|
1836
|
-
/* @__PURE__ */ jsx7("span", { className: "blade-chat-file-card-icon", children: downloading ? /* @__PURE__ */ jsx7(LoaderCircle, { size: 15, className: "animate-spin" }) : /* @__PURE__ */ jsx7(Icon2, { size: 15 }) }),
|
|
1837
|
-
/* @__PURE__ */ jsx7("span", { className: "blade-chat-file-card-name", children: name }),
|
|
1838
|
-
/* @__PURE__ */ jsx7(Download, { size: 13, className: "blade-chat-file-card-action" })
|
|
1839
|
-
]
|
|
1840
|
-
}
|
|
1841
|
-
),
|
|
1842
|
-
failed && /* @__PURE__ */ jsx7("span", { className: "blade-chat-file-card-error", children: "\u4E0B\u8F7D\u5931\u8D25" })
|
|
1843
|
-
] });
|
|
1844
|
-
}
|
|
1845
|
-
|
|
1846
|
-
// src/components/MarkdownContent.tsx
|
|
1847
|
-
import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1848
1715
|
var SYSTEM_REMINDER_RE = /<system-reminder>[\s\S]*?<\/system-reminder>/gi;
|
|
1849
1716
|
function CodeBlockPre({ children, node: _node, ...props }) {
|
|
1850
1717
|
const preRef = useRef5(null);
|
|
1851
|
-
const [copied, setCopied] =
|
|
1852
|
-
const [language, setLanguage] =
|
|
1718
|
+
const [copied, setCopied] = useState6(false);
|
|
1719
|
+
const [language, setLanguage] = useState6("");
|
|
1853
1720
|
useEffect4(() => {
|
|
1854
1721
|
const codeEl = preRef.current?.querySelector("code");
|
|
1855
1722
|
setLanguage(codeEl?.className.match(/language-(\S+)/)?.[1] ?? "");
|
|
@@ -1861,10 +1728,10 @@ function CodeBlockPre({ children, node: _node, ...props }) {
|
|
|
1861
1728
|
setTimeout(() => setCopied(false), 2e3);
|
|
1862
1729
|
}
|
|
1863
1730
|
};
|
|
1864
|
-
return /* @__PURE__ */
|
|
1865
|
-
/* @__PURE__ */
|
|
1866
|
-
/* @__PURE__ */
|
|
1867
|
-
/* @__PURE__ */
|
|
1731
|
+
return /* @__PURE__ */ jsxs6("div", { className: "blade-chat-codeblock not-prose my-3 overflow-hidden rounded-xl border border-[hsl(var(--border))]", children: [
|
|
1732
|
+
/* @__PURE__ */ jsxs6("div", { className: "blade-chat-codeblock-header flex h-[34px] items-center justify-between border-b border-[hsl(var(--border))] bg-[hsl(var(--muted))/0.5] pl-3.5 pr-1.5", children: [
|
|
1733
|
+
/* @__PURE__ */ jsx7("span", { className: "font-mono text-[12px] text-[hsl(var(--muted-foreground))]", children: language || "code" }),
|
|
1734
|
+
/* @__PURE__ */ jsxs6(
|
|
1868
1735
|
"button",
|
|
1869
1736
|
{
|
|
1870
1737
|
type: "button",
|
|
@@ -1874,13 +1741,13 @@ function CodeBlockPre({ children, node: _node, ...props }) {
|
|
|
1874
1741
|
copied ? "text-[hsl(var(--primary))]" : "text-[hsl(var(--muted-foreground))] hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))]"
|
|
1875
1742
|
),
|
|
1876
1743
|
children: [
|
|
1877
|
-
copied ? /* @__PURE__ */
|
|
1878
|
-
/* @__PURE__ */
|
|
1744
|
+
copied ? /* @__PURE__ */ jsx7(Check, { size: 12 }) : /* @__PURE__ */ jsx7(Copy, { size: 12 }),
|
|
1745
|
+
/* @__PURE__ */ jsx7("span", { children: copied ? "\u5DF2\u590D\u5236" : "\u590D\u5236" })
|
|
1879
1746
|
]
|
|
1880
1747
|
}
|
|
1881
1748
|
)
|
|
1882
1749
|
] }),
|
|
1883
|
-
/* @__PURE__ */
|
|
1750
|
+
/* @__PURE__ */ jsx7(
|
|
1884
1751
|
"pre",
|
|
1885
1752
|
{
|
|
1886
1753
|
ref: preRef,
|
|
@@ -1892,36 +1759,22 @@ function CodeBlockPre({ children, node: _node, ...props }) {
|
|
|
1892
1759
|
] });
|
|
1893
1760
|
}
|
|
1894
1761
|
function ExternalAnchor({ node: _node, children, ...props }) {
|
|
1895
|
-
return /* @__PURE__ */
|
|
1762
|
+
return /* @__PURE__ */ jsx7("a", { ...props, target: "_blank", rel: "noopener noreferrer", children });
|
|
1896
1763
|
}
|
|
1897
1764
|
var MARKDOWN_COMPONENTS = {
|
|
1898
1765
|
pre: CodeBlockPre,
|
|
1899
1766
|
a: ExternalAnchor
|
|
1900
1767
|
};
|
|
1901
|
-
var CUSTOM_ALLOWED_TAGS = {
|
|
1902
|
-
[FILE_CARD_TAG]: ["dataPath", "dataName", "data-path", "data-name"]
|
|
1903
|
-
};
|
|
1904
1768
|
function MarkdownContent({ children, className, mode, sessionId }) {
|
|
1905
|
-
const streaming = mode === "streaming";
|
|
1906
1769
|
const resolvedChildren = useMemo5(() => {
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
}, [children, sessionId, streaming]);
|
|
1911
|
-
const components = useMemo5(
|
|
1912
|
-
() => ({
|
|
1913
|
-
...MARKDOWN_COMPONENTS,
|
|
1914
|
-
[FILE_CARD_TAG]: (fileCardProps) => /* @__PURE__ */ jsx8(FileCard, { ...fileCardProps, sessionId })
|
|
1915
|
-
}),
|
|
1916
|
-
[sessionId]
|
|
1917
|
-
);
|
|
1918
|
-
return /* @__PURE__ */ jsx8(
|
|
1770
|
+
return children.replace(SYSTEM_REMINDER_RE, "");
|
|
1771
|
+
}, [children]);
|
|
1772
|
+
return /* @__PURE__ */ jsx7(
|
|
1919
1773
|
_r,
|
|
1920
1774
|
{
|
|
1921
1775
|
className: cn("blade-chat-markdown break-words", className),
|
|
1922
1776
|
mode: mode ?? "static",
|
|
1923
|
-
components,
|
|
1924
|
-
allowedTags: CUSTOM_ALLOWED_TAGS,
|
|
1777
|
+
components: MARKDOWN_COMPONENTS,
|
|
1925
1778
|
children: resolvedChildren
|
|
1926
1779
|
},
|
|
1927
1780
|
sessionId ?? "no-session"
|
|
@@ -1929,17 +1782,17 @@ function MarkdownContent({ children, className, mode, sessionId }) {
|
|
|
1929
1782
|
}
|
|
1930
1783
|
|
|
1931
1784
|
// src/components/Shimmer.tsx
|
|
1932
|
-
import { jsx as
|
|
1785
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
1933
1786
|
function Shimmer({ children = "\u6B63\u5728\u601D\u8003...", className }) {
|
|
1934
|
-
return /* @__PURE__ */
|
|
1787
|
+
return /* @__PURE__ */ jsx8("span", { className: cn("blade-shimmer-text text-sm font-medium", className), children });
|
|
1935
1788
|
}
|
|
1936
1789
|
|
|
1937
1790
|
// src/components/ToolCallBlock.tsx
|
|
1938
|
-
import { useState as
|
|
1791
|
+
import { useState as useState8 } from "react";
|
|
1939
1792
|
|
|
1940
1793
|
// src/components/AskUserQuestionBlock.tsx
|
|
1941
|
-
import { useEffect as useEffect5, useMemo as useMemo6, useState as
|
|
1942
|
-
import { jsx as
|
|
1794
|
+
import { useEffect as useEffect5, useMemo as useMemo6, useState as useState7 } from "react";
|
|
1795
|
+
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1943
1796
|
function AskUserQuestionBlock({
|
|
1944
1797
|
data,
|
|
1945
1798
|
answered,
|
|
@@ -1948,10 +1801,10 @@ function AskUserQuestionBlock({
|
|
|
1948
1801
|
answerData,
|
|
1949
1802
|
onAnswer
|
|
1950
1803
|
}) {
|
|
1951
|
-
const [selections, setSelections] =
|
|
1952
|
-
const [customTexts, setCustomTexts] =
|
|
1953
|
-
const [usingCustom, setUsingCustom] =
|
|
1954
|
-
const [submitted, setSubmitted] =
|
|
1804
|
+
const [selections, setSelections] = useState7(/* @__PURE__ */ new Map());
|
|
1805
|
+
const [customTexts, setCustomTexts] = useState7(/* @__PURE__ */ new Map());
|
|
1806
|
+
const [usingCustom, setUsingCustom] = useState7(/* @__PURE__ */ new Set());
|
|
1807
|
+
const [submitted, setSubmitted] = useState7(false);
|
|
1955
1808
|
useEffect5(() => {
|
|
1956
1809
|
if (sessionStatus === "failed" || sessionStatus === "interrupted") {
|
|
1957
1810
|
setSubmitted(false);
|
|
@@ -2042,7 +1895,7 @@ ${parts.join("\n")}`;
|
|
|
2042
1895
|
setSubmitted(true);
|
|
2043
1896
|
onAnswer(text, toolCallId, nextAnswerData);
|
|
2044
1897
|
};
|
|
2045
|
-
return /* @__PURE__ */
|
|
1898
|
+
return /* @__PURE__ */ jsxs7(
|
|
2046
1899
|
"div",
|
|
2047
1900
|
{
|
|
2048
1901
|
className: cn(
|
|
@@ -2050,12 +1903,12 @@ ${parts.join("\n")}`;
|
|
|
2050
1903
|
answered ? "max-w-2xl space-y-3 p-3 text-xs text-[hsl(var(--muted-foreground))] opacity-80" : "max-w-lg space-y-5 p-4 text-sm"
|
|
2051
1904
|
),
|
|
2052
1905
|
children: [
|
|
2053
|
-
data.source_loop?.description && /* @__PURE__ */
|
|
1906
|
+
data.source_loop?.description && /* @__PURE__ */ jsxs7("div", { className: "rounded-lg bg-[hsl(var(--muted)/0.35)] px-3 py-2 text-xs text-[hsl(var(--muted-foreground))]", children: [
|
|
2054
1907
|
"\u5B50\u667A\u80FD\u4F53\u300C",
|
|
2055
1908
|
data.source_loop.description,
|
|
2056
1909
|
"\u300D\u5728\u7B49\u5F85\u4F60\u7684\u56DE\u7B54"
|
|
2057
1910
|
] }),
|
|
2058
|
-
data.questions.map((q, qIdx) => /* @__PURE__ */
|
|
1911
|
+
data.questions.map((q, qIdx) => /* @__PURE__ */ jsx9(
|
|
2059
1912
|
QuestionCard,
|
|
2060
1913
|
{
|
|
2061
1914
|
question: q,
|
|
@@ -2070,7 +1923,7 @@ ${parts.join("\n")}`;
|
|
|
2070
1923
|
},
|
|
2071
1924
|
q.question
|
|
2072
1925
|
)),
|
|
2073
|
-
!answered && !submitted && onAnswer && /* @__PURE__ */
|
|
1926
|
+
!answered && !submitted && onAnswer && /* @__PURE__ */ jsx9(
|
|
2074
1927
|
"button",
|
|
2075
1928
|
{
|
|
2076
1929
|
type: "button",
|
|
@@ -2080,14 +1933,14 @@ ${parts.join("\n")}`;
|
|
|
2080
1933
|
children: allAnswered ? "\u786E\u8BA4" : "\u8BF7\u5148\u9009\u62E9\u4E00\u4E2A\u9009\u9879"
|
|
2081
1934
|
}
|
|
2082
1935
|
),
|
|
2083
|
-
submitted && !answered && /* @__PURE__ */
|
|
1936
|
+
submitted && !answered && /* @__PURE__ */ jsxs7(
|
|
2084
1937
|
"button",
|
|
2085
1938
|
{
|
|
2086
1939
|
type: "button",
|
|
2087
1940
|
disabled: true,
|
|
2088
1941
|
className: "flex w-full items-center justify-center gap-2 rounded-lg bg-[hsl(var(--primary))] px-4 py-2 text-xs font-semibold text-[hsl(var(--primary-foreground))] opacity-80",
|
|
2089
1942
|
children: [
|
|
2090
|
-
/* @__PURE__ */
|
|
1943
|
+
/* @__PURE__ */ jsx9(LoaderCircle, { size: 14, className: "animate-spin" }),
|
|
2091
1944
|
"\u786E\u8BA4\u4E2D"
|
|
2092
1945
|
]
|
|
2093
1946
|
}
|
|
@@ -2108,30 +1961,30 @@ function QuestionCard({
|
|
|
2108
1961
|
onCustomChange
|
|
2109
1962
|
}) {
|
|
2110
1963
|
const multi = question.multiSelect ?? false;
|
|
2111
|
-
return /* @__PURE__ */
|
|
2112
|
-
/* @__PURE__ */
|
|
2113
|
-
/* @__PURE__ */
|
|
1964
|
+
return /* @__PURE__ */ jsxs7("div", { children: [
|
|
1965
|
+
/* @__PURE__ */ jsxs7("div", { className: cn("flex items-start gap-2", answered ? "mb-2" : "mb-3"), children: [
|
|
1966
|
+
/* @__PURE__ */ jsx9(
|
|
2114
1967
|
MessageSquareMore,
|
|
2115
1968
|
{
|
|
2116
1969
|
size: answered ? 12 : 13,
|
|
2117
1970
|
className: "mt-0.5 shrink-0 text-[hsl(var(--primary))]"
|
|
2118
1971
|
}
|
|
2119
1972
|
),
|
|
2120
|
-
/* @__PURE__ */
|
|
1973
|
+
/* @__PURE__ */ jsx9(
|
|
2121
1974
|
"div",
|
|
2122
1975
|
{
|
|
2123
1976
|
className: cn(
|
|
2124
1977
|
"min-w-0 flex-1 font-medium text-[hsl(var(--foreground))]",
|
|
2125
1978
|
answered ? "text-xs" : "text-sm"
|
|
2126
1979
|
),
|
|
2127
|
-
children: /* @__PURE__ */
|
|
1980
|
+
children: /* @__PURE__ */ jsx9(MarkdownContent, { className: "blade-chat-prose", children: question.question })
|
|
2128
1981
|
}
|
|
2129
1982
|
)
|
|
2130
1983
|
] }),
|
|
2131
|
-
/* @__PURE__ */
|
|
1984
|
+
/* @__PURE__ */ jsxs7("div", { className: cn("flex flex-col pl-5", answered ? "gap-1" : "gap-1.5"), children: [
|
|
2132
1985
|
question.options.map((opt, optIdx) => {
|
|
2133
1986
|
const isSel = selected.has(optIdx);
|
|
2134
|
-
return /* @__PURE__ */
|
|
1987
|
+
return /* @__PURE__ */ jsxs7(
|
|
2135
1988
|
"button",
|
|
2136
1989
|
{
|
|
2137
1990
|
type: "button",
|
|
@@ -2145,14 +1998,14 @@ function QuestionCard({
|
|
|
2145
1998
|
answered && "cursor-default opacity-70"
|
|
2146
1999
|
),
|
|
2147
2000
|
children: [
|
|
2148
|
-
multi && /* @__PURE__ */
|
|
2001
|
+
multi && /* @__PURE__ */ jsx9(
|
|
2149
2002
|
"div",
|
|
2150
2003
|
{
|
|
2151
2004
|
className: cn(
|
|
2152
2005
|
"mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded border transition-colors",
|
|
2153
2006
|
isSel && !answered ? "border-[hsl(var(--primary-foreground)/0.6)] bg-[hsl(var(--primary-foreground)/0.2)]" : isSel ? "border-[hsl(var(--primary)/0.45)] bg-[hsl(var(--primary)/0.12)]" : "border-[hsl(var(--border))]"
|
|
2154
2007
|
),
|
|
2155
|
-
children: isSel && /* @__PURE__ */
|
|
2008
|
+
children: isSel && /* @__PURE__ */ jsx9(
|
|
2156
2009
|
Check,
|
|
2157
2010
|
{
|
|
2158
2011
|
size: 9,
|
|
@@ -2161,9 +2014,9 @@ function QuestionCard({
|
|
|
2161
2014
|
)
|
|
2162
2015
|
}
|
|
2163
2016
|
),
|
|
2164
|
-
/* @__PURE__ */
|
|
2165
|
-
/* @__PURE__ */
|
|
2166
|
-
opt.description && /* @__PURE__ */
|
|
2017
|
+
/* @__PURE__ */ jsxs7("div", { className: "min-w-0", children: [
|
|
2018
|
+
/* @__PURE__ */ jsx9("div", { className: cn("font-medium", answered ? "text-xs" : "text-[13px]"), children: opt.label }),
|
|
2019
|
+
opt.description && /* @__PURE__ */ jsx9(
|
|
2167
2020
|
"div",
|
|
2168
2021
|
{
|
|
2169
2022
|
className: cn(
|
|
@@ -2180,7 +2033,7 @@ function QuestionCard({
|
|
|
2180
2033
|
opt.label
|
|
2181
2034
|
);
|
|
2182
2035
|
}),
|
|
2183
|
-
answered && !isCustom ? null : /* @__PURE__ */
|
|
2036
|
+
answered && !isCustom ? null : /* @__PURE__ */ jsxs7(
|
|
2184
2037
|
"div",
|
|
2185
2038
|
{
|
|
2186
2039
|
className: cn(
|
|
@@ -2190,8 +2043,8 @@ function QuestionCard({
|
|
|
2190
2043
|
answered && "cursor-default opacity-70"
|
|
2191
2044
|
),
|
|
2192
2045
|
children: [
|
|
2193
|
-
/* @__PURE__ */
|
|
2194
|
-
/* @__PURE__ */
|
|
2046
|
+
/* @__PURE__ */ jsx9("span", { className: "shrink-0 text-xs text-[hsl(var(--muted-foreground))]", children: "\u5176\u4ED6\uFF1A" }),
|
|
2047
|
+
/* @__PURE__ */ jsx9(
|
|
2195
2048
|
"input",
|
|
2196
2049
|
{
|
|
2197
2050
|
type: "text",
|
|
@@ -2259,7 +2112,7 @@ function normalizeOptionItem(value) {
|
|
|
2259
2112
|
}
|
|
2260
2113
|
|
|
2261
2114
|
// src/components/ToolCallBlock.tsx
|
|
2262
|
-
import { Fragment, jsx as
|
|
2115
|
+
import { Fragment, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
2263
2116
|
function resolveAskQuestionState({
|
|
2264
2117
|
toolStatus,
|
|
2265
2118
|
hasAnswerData,
|
|
@@ -2279,12 +2132,12 @@ function ToolCallBlock({
|
|
|
2279
2132
|
sessionStatus,
|
|
2280
2133
|
renderer
|
|
2281
2134
|
}) {
|
|
2282
|
-
const [expanded, setExpanded] =
|
|
2135
|
+
const [expanded, setExpanded] = useState8(false);
|
|
2283
2136
|
const normalizedName = formatToolName(toolCall.name);
|
|
2284
2137
|
if (renderer) {
|
|
2285
2138
|
const custom = renderer(toolCall);
|
|
2286
2139
|
if (custom !== null && custom !== void 0) {
|
|
2287
|
-
return /* @__PURE__ */
|
|
2140
|
+
return /* @__PURE__ */ jsx10(Fragment, { children: custom });
|
|
2288
2141
|
}
|
|
2289
2142
|
}
|
|
2290
2143
|
if (normalizedName === "AskUserQuestion") {
|
|
@@ -2296,7 +2149,7 @@ function ToolCallBlock({
|
|
|
2296
2149
|
});
|
|
2297
2150
|
const canAnswer = questionState.awaitingAnswer && Boolean(onAnswer);
|
|
2298
2151
|
if (askData) {
|
|
2299
|
-
return /* @__PURE__ */
|
|
2152
|
+
return /* @__PURE__ */ jsx10(
|
|
2300
2153
|
AskUserQuestionBlock,
|
|
2301
2154
|
{
|
|
2302
2155
|
data: askData,
|
|
@@ -2309,24 +2162,24 @@ function ToolCallBlock({
|
|
|
2309
2162
|
);
|
|
2310
2163
|
}
|
|
2311
2164
|
if (toolCall.status === "pending") {
|
|
2312
|
-
return /* @__PURE__ */
|
|
2313
|
-
/* @__PURE__ */
|
|
2314
|
-
/* @__PURE__ */
|
|
2165
|
+
return /* @__PURE__ */ jsxs8("div", { className: "ml-4 flex max-w-lg items-center gap-2 rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] p-4 text-sm text-[hsl(var(--muted-foreground))]", children: [
|
|
2166
|
+
/* @__PURE__ */ jsx10(LoaderCircle, { size: 14, className: "animate-spin" }),
|
|
2167
|
+
/* @__PURE__ */ jsx10("span", { children: "\u6B63\u5728\u51C6\u5907\u95EE\u9898\u2026" })
|
|
2315
2168
|
] });
|
|
2316
2169
|
}
|
|
2317
|
-
return /* @__PURE__ */
|
|
2318
|
-
/* @__PURE__ */
|
|
2319
|
-
/* @__PURE__ */
|
|
2170
|
+
return /* @__PURE__ */ jsxs8("div", { className: "ml-4 max-w-lg rounded-xl border border-amber-500/35 bg-amber-500/10 p-4 text-sm text-[hsl(var(--foreground))]", children: [
|
|
2171
|
+
/* @__PURE__ */ jsx10("div", { className: "font-semibold", children: "\u9009\u62E9\u9898\u5185\u5BB9\u6682\u65F6\u65E0\u6CD5\u663E\u793A" }),
|
|
2172
|
+
/* @__PURE__ */ jsx10("div", { className: "mt-1 text-xs leading-5 text-[hsl(var(--muted-foreground))]", children: "\u6536\u5230\u7684\u4EA4\u4E92\u6570\u636E\u4E0D\u5B8C\u6574\u3002\u8BF7\u8BA9\u667A\u80FD\u4F53\u91CD\u65B0\u63D0\u95EE\u3002" })
|
|
2320
2173
|
] });
|
|
2321
2174
|
}
|
|
2322
2175
|
const tone = getToolTone(toolCall.status);
|
|
2323
2176
|
const displayName = getToolDisplayLabel(toolCall);
|
|
2324
2177
|
const toneClass = tone === "red" ? "border-l-[hsl(var(--muted-foreground)/0.5)]" : tone === "amber" ? "border-l-amber-400" : tone === "blue" ? "border-l-blue-500" : "border-l-[hsl(var(--primary))]";
|
|
2325
|
-
const statusIcon = toolCall.status === "pending" ? /* @__PURE__ */
|
|
2178
|
+
const statusIcon = toolCall.status === "pending" ? /* @__PURE__ */ jsx10(LoaderCircle, { size: 11, className: "animate-spin" }) : toolCall.status === "awaiting_answer" ? /* @__PURE__ */ jsx10(MessageSquareMore, { size: 11 }) : toolCall.status === "cancelled" || toolCall.status === "error" ? /* @__PURE__ */ jsx10(X, { size: 11 }) : /* @__PURE__ */ jsx10(Check, { size: 11 });
|
|
2326
2179
|
const statusTextClass = tone === "red" ? "text-[hsl(var(--muted-foreground))]" : tone === "amber" ? "text-amber-300" : tone === "blue" ? "text-blue-300" : "text-[hsl(var(--primary))]";
|
|
2327
|
-
return /* @__PURE__ */
|
|
2328
|
-
/* @__PURE__ */
|
|
2329
|
-
/* @__PURE__ */
|
|
2180
|
+
return /* @__PURE__ */ jsxs8("div", { className: "blade-chat-tool ml-4 text-xs", children: [
|
|
2181
|
+
/* @__PURE__ */ jsxs8("div", { className: cn("border-l-[3px] flex items-center gap-2 px-3 py-2", toneClass), children: [
|
|
2182
|
+
/* @__PURE__ */ jsxs8(
|
|
2330
2183
|
"button",
|
|
2331
2184
|
{
|
|
2332
2185
|
type: "button",
|
|
@@ -2334,7 +2187,7 @@ function ToolCallBlock({
|
|
|
2334
2187
|
className: "flex min-w-0 flex-1 items-center gap-2 text-left transition-colors hover:bg-white/3 focus-visible:ring-1 focus-visible:ring-[hsl(var(--ring))] focus:outline-none",
|
|
2335
2188
|
"aria-expanded": expanded,
|
|
2336
2189
|
children: [
|
|
2337
|
-
/* @__PURE__ */
|
|
2190
|
+
/* @__PURE__ */ jsx10(
|
|
2338
2191
|
ChevronRight,
|
|
2339
2192
|
{
|
|
2340
2193
|
size: 11,
|
|
@@ -2344,24 +2197,24 @@ function ToolCallBlock({
|
|
|
2344
2197
|
)
|
|
2345
2198
|
}
|
|
2346
2199
|
),
|
|
2347
|
-
/* @__PURE__ */
|
|
2200
|
+
/* @__PURE__ */ jsxs8("span", { className: cn("flex shrink-0 items-center gap-1 text-[10px]", statusTextClass), children: [
|
|
2348
2201
|
statusIcon,
|
|
2349
|
-
/* @__PURE__ */
|
|
2202
|
+
/* @__PURE__ */ jsx10("span", { children: getToolStatusLabel(toolCall.status) })
|
|
2350
2203
|
] }),
|
|
2351
|
-
/* @__PURE__ */
|
|
2204
|
+
/* @__PURE__ */ jsx10("span", { className: "min-w-0 flex-1 truncate font-medium text-[hsl(var(--foreground))]", children: displayName })
|
|
2352
2205
|
]
|
|
2353
2206
|
}
|
|
2354
2207
|
),
|
|
2355
|
-
typeof toolCall.duration_ms === "number" && toolCall.duration_ms > 0 && /* @__PURE__ */
|
|
2208
|
+
typeof toolCall.duration_ms === "number" && toolCall.duration_ms > 0 && /* @__PURE__ */ jsx10("span", { className: "shrink-0 font-mono text-[10px] text-[hsl(var(--muted-foreground))]", children: formatToolDuration(toolCall.duration_ms) })
|
|
2356
2209
|
] }),
|
|
2357
|
-
expanded && /* @__PURE__ */
|
|
2358
|
-
/* @__PURE__ */
|
|
2359
|
-
/* @__PURE__ */
|
|
2360
|
-
/* @__PURE__ */
|
|
2361
|
-
/* @__PURE__ */
|
|
2362
|
-
toolCall.result != null && /* @__PURE__ */
|
|
2363
|
-
/* @__PURE__ */
|
|
2364
|
-
/* @__PURE__ */
|
|
2210
|
+
expanded && /* @__PURE__ */ jsxs8("div", { className: "blade-chat-tool-detail ml-4 mt-1 rounded-xl bg-[hsl(var(--card))] px-3 py-3", children: [
|
|
2211
|
+
/* @__PURE__ */ jsx10("div", { className: "mb-1 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u5DE5\u5177" }),
|
|
2212
|
+
/* @__PURE__ */ jsx10("div", { className: "mb-3 font-mono text-[11px] text-[hsl(var(--foreground))]", children: normalizedName }),
|
|
2213
|
+
/* @__PURE__ */ jsx10("div", { className: "mb-1 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u53C2\u6570" }),
|
|
2214
|
+
/* @__PURE__ */ jsx10("pre", { className: "overflow-x-auto whitespace-pre-wrap rounded-md bg-[hsl(var(--muted))] p-2 font-mono text-[11px] text-[hsl(var(--foreground))]", children: formatToolArgs(toolCall.arguments) }),
|
|
2215
|
+
toolCall.result != null && /* @__PURE__ */ jsxs8(Fragment, { children: [
|
|
2216
|
+
/* @__PURE__ */ jsx10("div", { className: "mb-1 mt-3 text-[10px] uppercase tracking-wider text-[hsl(var(--muted-foreground))]", children: "\u7ED3\u679C" }),
|
|
2217
|
+
/* @__PURE__ */ jsx10("pre", { className: "max-h-[400px] overflow-auto whitespace-pre-wrap rounded-md bg-[hsl(var(--muted))] p-2 font-mono text-[11px] text-[hsl(var(--foreground))]", children: formatToolResult(toolCall.result) })
|
|
2365
2218
|
] })
|
|
2366
2219
|
] })
|
|
2367
2220
|
] });
|
|
@@ -2379,11 +2232,11 @@ function buildAskUserPayload(argumentsJson) {
|
|
|
2379
2232
|
}
|
|
2380
2233
|
|
|
2381
2234
|
// src/components/AssistantTurnBlock.tsx
|
|
2382
|
-
import { jsx as
|
|
2235
|
+
import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
2383
2236
|
function ThinkingBlock({ reasoning, isStreaming }) {
|
|
2384
|
-
const [open, setOpen] =
|
|
2385
|
-
return /* @__PURE__ */
|
|
2386
|
-
/* @__PURE__ */
|
|
2237
|
+
const [open, setOpen] = useState9(false);
|
|
2238
|
+
return /* @__PURE__ */ jsxs9("div", { className: "blade-chat-thinking ml-4 text-sm", children: [
|
|
2239
|
+
/* @__PURE__ */ jsxs9(
|
|
2387
2240
|
"button",
|
|
2388
2241
|
{
|
|
2389
2242
|
type: "button",
|
|
@@ -2391,14 +2244,14 @@ function ThinkingBlock({ reasoning, isStreaming }) {
|
|
|
2391
2244
|
"aria-expanded": open,
|
|
2392
2245
|
className: "inline-flex items-center gap-1.5 text-[hsl(var(--muted-foreground))] transition-colors hover:text-[hsl(var(--foreground))]",
|
|
2393
2246
|
children: [
|
|
2394
|
-
/* @__PURE__ */
|
|
2395
|
-
isStreaming ? /* @__PURE__ */
|
|
2396
|
-
/* @__PURE__ */
|
|
2247
|
+
/* @__PURE__ */ jsx11(Brain, { size: 12, className: "shrink-0" }),
|
|
2248
|
+
isStreaming ? /* @__PURE__ */ jsx11(Shimmer, { className: "text-xs", children: "\u6B63\u5728\u601D\u8003" }) : /* @__PURE__ */ jsx11("span", { children: "\u601D\u8003\u8FC7\u7A0B" }),
|
|
2249
|
+
/* @__PURE__ */ jsxs9("span", { className: "text-[hsl(var(--muted-foreground))]/70", children: [
|
|
2397
2250
|
"\xB7 ",
|
|
2398
2251
|
new Intl.NumberFormat("zh-CN").format(reasoning.length),
|
|
2399
2252
|
" \u5B57"
|
|
2400
2253
|
] }),
|
|
2401
|
-
/* @__PURE__ */
|
|
2254
|
+
/* @__PURE__ */ jsx11(
|
|
2402
2255
|
ChevronDown,
|
|
2403
2256
|
{
|
|
2404
2257
|
size: 12,
|
|
@@ -2408,7 +2261,7 @@ function ThinkingBlock({ reasoning, isStreaming }) {
|
|
|
2408
2261
|
]
|
|
2409
2262
|
}
|
|
2410
2263
|
),
|
|
2411
|
-
open && /* @__PURE__ */
|
|
2264
|
+
open && /* @__PURE__ */ jsx11("div", { className: "mt-1.5 whitespace-pre-wrap border-l-2 border-[hsl(var(--border))] pl-3 text-[11px] leading-5 text-[hsl(var(--muted-foreground))]", children: reasoning })
|
|
2412
2265
|
] });
|
|
2413
2266
|
}
|
|
2414
2267
|
function getMessageText(message) {
|
|
@@ -2434,21 +2287,21 @@ function AssistantTurnBlock({
|
|
|
2434
2287
|
(message) => getMessageText(message) || message.reasoning || (message.tool_calls?.length ?? 0) > 0
|
|
2435
2288
|
);
|
|
2436
2289
|
const latestReasoningIndex = isStreaming ? findLatestReasoningMessageIndex(messages) : -1;
|
|
2437
|
-
return /* @__PURE__ */
|
|
2438
|
-
hasInterrupted && /* @__PURE__ */
|
|
2290
|
+
return /* @__PURE__ */ jsxs9("div", { className: "blade-chat-assistant-turn flex flex-col gap-3", children: [
|
|
2291
|
+
hasInterrupted && /* @__PURE__ */ jsx11("div", { className: "ml-4 w-fit rounded-full border border-amber-500/30 bg-amber-500/10 px-2.5 py-1 text-[10px] font-medium uppercase tracking-[0.12em] text-amber-300", children: "\u5DF2\u4E2D\u65AD" }),
|
|
2439
2292
|
messages.map((message, index) => {
|
|
2440
2293
|
const isLast = index === messages.length - 1;
|
|
2441
2294
|
const streamingThis = isStreaming && isLast;
|
|
2442
2295
|
const text = getMessageText(message);
|
|
2443
2296
|
const toolCalls = message.tool_calls ?? [];
|
|
2444
2297
|
const showReasoning = !!message.reasoning && (!isStreaming || index === latestReasoningIndex);
|
|
2445
|
-
return /* @__PURE__ */
|
|
2298
|
+
return /* @__PURE__ */ jsxs9(
|
|
2446
2299
|
"div",
|
|
2447
2300
|
{
|
|
2448
2301
|
className: "flex flex-col gap-3",
|
|
2449
2302
|
children: [
|
|
2450
|
-
showReasoning && message.reasoning && /* @__PURE__ */
|
|
2451
|
-
text && /* @__PURE__ */
|
|
2303
|
+
showReasoning && message.reasoning && /* @__PURE__ */ jsx11(ThinkingBlock, { reasoning: message.reasoning, isStreaming: streamingThis && !text }),
|
|
2304
|
+
text && /* @__PURE__ */ jsx11("div", { className: "blade-chat-assistant-text text-[15px] leading-8 text-[hsl(var(--foreground))]", children: /* @__PURE__ */ jsx11(
|
|
2452
2305
|
MarkdownContent,
|
|
2453
2306
|
{
|
|
2454
2307
|
mode: streamingThis ? "streaming" : "static",
|
|
@@ -2457,8 +2310,8 @@ function AssistantTurnBlock({
|
|
|
2457
2310
|
children: text
|
|
2458
2311
|
}
|
|
2459
2312
|
) }),
|
|
2460
|
-
toolCalls.length > 0 && /* @__PURE__ */
|
|
2461
|
-
(toolCall) => formatToolName(toolCall.name) === "Agent" ? /* @__PURE__ */
|
|
2313
|
+
toolCalls.length > 0 && /* @__PURE__ */ jsx11("div", { className: "flex flex-col gap-2", children: toolCalls.map(
|
|
2314
|
+
(toolCall) => formatToolName(toolCall.name) === "Agent" ? /* @__PURE__ */ jsx11(AgentLoopBlock, { toolCall }, toolCall.id) : /* @__PURE__ */ jsx11(
|
|
2462
2315
|
ToolCallBlock,
|
|
2463
2316
|
{
|
|
2464
2317
|
toolCall,
|
|
@@ -2476,13 +2329,13 @@ function AssistantTurnBlock({
|
|
|
2476
2329
|
message.entry_id ?? `${message.timestamp ?? "assistant"}-${index}`
|
|
2477
2330
|
);
|
|
2478
2331
|
}),
|
|
2479
|
-
isStreaming && !hasAnyContent && /* @__PURE__ */
|
|
2332
|
+
isStreaming && !hasAnyContent && /* @__PURE__ */ jsx11(Shimmer, { className: "ml-4", children: "\u6B63\u5728\u751F\u6210..." })
|
|
2480
2333
|
] });
|
|
2481
2334
|
}
|
|
2482
2335
|
|
|
2483
2336
|
// src/components/RenderErrorBoundary.tsx
|
|
2484
2337
|
import { Component } from "react";
|
|
2485
|
-
import { jsx as
|
|
2338
|
+
import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
2486
2339
|
function getFirstComponentName(componentStack) {
|
|
2487
2340
|
const match = componentStack.match(/\n\s+at\s+([^\s(]+)/);
|
|
2488
2341
|
return match?.[1] ?? null;
|
|
@@ -2515,23 +2368,408 @@ var RenderErrorBoundary = class extends Component {
|
|
|
2515
2368
|
return children;
|
|
2516
2369
|
}
|
|
2517
2370
|
const componentName = getFirstComponentName(componentStack);
|
|
2518
|
-
return /* @__PURE__ */
|
|
2519
|
-
/* @__PURE__ */
|
|
2520
|
-
/* @__PURE__ */
|
|
2521
|
-
/* @__PURE__ */
|
|
2371
|
+
return /* @__PURE__ */ jsx12("div", { className: "blade-chat-render-error rounded-xl border border-amber-500/30 bg-amber-500/8 px-4 py-3 text-sm text-amber-100", children: /* @__PURE__ */ jsxs10("div", { className: "flex items-start gap-2", children: [
|
|
2372
|
+
/* @__PURE__ */ jsx12(TriangleAlert, { className: "mt-0.5 h-4 w-4 shrink-0 text-amber-300" }),
|
|
2373
|
+
/* @__PURE__ */ jsxs10("div", { className: "min-w-0 flex-1", children: [
|
|
2374
|
+
/* @__PURE__ */ jsxs10("div", { className: "font-medium", children: [
|
|
2522
2375
|
label,
|
|
2523
2376
|
"\u6E32\u67D3\u5931\u8D25"
|
|
2524
2377
|
] }),
|
|
2525
|
-
/* @__PURE__ */
|
|
2378
|
+
/* @__PURE__ */ jsxs10("div", { className: "mt-1 break-words text-xs leading-5 text-amber-100/75", children: [
|
|
2526
2379
|
componentName ? `\u7EC4\u4EF6\uFF1A${componentName}\u3002` : null,
|
|
2527
2380
|
error.message || "\u53D1\u751F\u4E86\u672A\u9884\u671F\u7684\u6E32\u67D3\u9519\u8BEF\u3002"
|
|
2528
2381
|
] }),
|
|
2529
|
-
details ? /* @__PURE__ */
|
|
2382
|
+
details ? /* @__PURE__ */ jsx12("div", { className: "mt-1 truncate text-xs text-amber-100/55", children: details }) : null
|
|
2530
2383
|
] })
|
|
2531
2384
|
] }) });
|
|
2532
2385
|
}
|
|
2533
2386
|
};
|
|
2534
2387
|
|
|
2388
|
+
// src/components/PostChatFollowupBlock.tsx
|
|
2389
|
+
import { useCallback as useCallback5, useEffect as useEffect6, useRef as useRef6, useState as useState10 } from "react";
|
|
2390
|
+
import { Fragment as Fragment2, jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2391
|
+
function emitInteraction(callback, event) {
|
|
2392
|
+
try {
|
|
2393
|
+
callback?.(event);
|
|
2394
|
+
} catch {
|
|
2395
|
+
}
|
|
2396
|
+
}
|
|
2397
|
+
function basename(path) {
|
|
2398
|
+
return path.split(/[\\/]/).filter(Boolean).pop() || path;
|
|
2399
|
+
}
|
|
2400
|
+
function isVideo(path) {
|
|
2401
|
+
return /\.(?:mp4|mov|webm|mkv|avi|m4v)$/i.test(path);
|
|
2402
|
+
}
|
|
2403
|
+
function ArtifactCard({
|
|
2404
|
+
artifact,
|
|
2405
|
+
sessionId,
|
|
2406
|
+
assistantEntryId,
|
|
2407
|
+
artifactIndex,
|
|
2408
|
+
onInteraction,
|
|
2409
|
+
onArtifactOpened
|
|
2410
|
+
}) {
|
|
2411
|
+
const client = useBladeClient();
|
|
2412
|
+
const [downloading, setDownloading] = useState10(false);
|
|
2413
|
+
const name = artifact.label || basename(artifact.target);
|
|
2414
|
+
if (artifact.kind === "link") {
|
|
2415
|
+
return /* @__PURE__ */ jsxs11(
|
|
2416
|
+
"a",
|
|
2417
|
+
{
|
|
2418
|
+
href: artifact.target,
|
|
2419
|
+
target: "_blank",
|
|
2420
|
+
rel: "noopener noreferrer",
|
|
2421
|
+
onClick: () => onArtifactOpened(artifactIndex, "link"),
|
|
2422
|
+
title: `${name}
|
|
2423
|
+
${artifact.target}`,
|
|
2424
|
+
className: "group relative flex min-w-0 items-center gap-1.5 rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-2 py-1.5 text-xs text-[hsl(var(--card-foreground))] hover:bg-[hsl(var(--accent))]",
|
|
2425
|
+
children: [
|
|
2426
|
+
/* @__PURE__ */ jsx13(Globe, { size: 15, className: "shrink-0 text-[hsl(var(--primary))]" }),
|
|
2427
|
+
/* @__PURE__ */ jsx13("span", { className: "min-w-0 flex-1 truncate font-medium", children: name }),
|
|
2428
|
+
/* @__PURE__ */ jsx13(ArrowUpRight, { size: 13, className: "absolute right-2 opacity-0 group-hover:opacity-100 group-focus-visible:opacity-100" })
|
|
2429
|
+
]
|
|
2430
|
+
}
|
|
2431
|
+
);
|
|
2432
|
+
}
|
|
2433
|
+
const Icon2 = isVideo(artifact.target) ? Film : File;
|
|
2434
|
+
return /* @__PURE__ */ jsxs11(
|
|
2435
|
+
"button",
|
|
2436
|
+
{
|
|
2437
|
+
type: "button",
|
|
2438
|
+
disabled: !sessionId || downloading,
|
|
2439
|
+
onClick: async () => {
|
|
2440
|
+
if (!sessionId || downloading) return;
|
|
2441
|
+
setDownloading(true);
|
|
2442
|
+
emitInteraction(onInteraction, {
|
|
2443
|
+
type: "artifact_download_started",
|
|
2444
|
+
sessionId,
|
|
2445
|
+
assistantEntryId,
|
|
2446
|
+
artifactIndex,
|
|
2447
|
+
artifactKind: "file"
|
|
2448
|
+
});
|
|
2449
|
+
try {
|
|
2450
|
+
await client.sessions.downloadFile(sessionId, artifact.target, basename(artifact.target));
|
|
2451
|
+
emitInteraction(onInteraction, {
|
|
2452
|
+
type: "artifact_download_succeeded",
|
|
2453
|
+
sessionId,
|
|
2454
|
+
assistantEntryId,
|
|
2455
|
+
artifactIndex,
|
|
2456
|
+
artifactKind: "file"
|
|
2457
|
+
});
|
|
2458
|
+
} catch {
|
|
2459
|
+
} finally {
|
|
2460
|
+
setDownloading(false);
|
|
2461
|
+
}
|
|
2462
|
+
},
|
|
2463
|
+
title: name,
|
|
2464
|
+
"aria-label": `\u4E0B\u8F7D ${name}`,
|
|
2465
|
+
className: "group relative flex min-w-0 items-center gap-1.5 rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--card))] px-2 py-1.5 text-left text-xs text-[hsl(var(--card-foreground))] hover:bg-[hsl(var(--accent))] disabled:opacity-60",
|
|
2466
|
+
children: [
|
|
2467
|
+
/* @__PURE__ */ jsx13(Icon2, { size: 15, className: "shrink-0 text-[hsl(var(--primary))]" }),
|
|
2468
|
+
/* @__PURE__ */ jsx13("span", { className: "min-w-0 flex-1 truncate font-medium", children: name }),
|
|
2469
|
+
/* @__PURE__ */ jsx13(Download, { size: 13, className: "absolute right-2 opacity-0 group-hover:opacity-100 group-focus-visible:opacity-100" })
|
|
2470
|
+
]
|
|
2471
|
+
}
|
|
2472
|
+
);
|
|
2473
|
+
}
|
|
2474
|
+
var FEEDBACK_REASONS = [
|
|
2475
|
+
{ value: "not_solved", label: "\u6CA1\u89E3\u51B3\u95EE\u9898" },
|
|
2476
|
+
{ value: "inaccurate", label: "\u5185\u5BB9\u4E0D\u51C6\u786E" },
|
|
2477
|
+
{ value: "incomplete", label: "\u5185\u5BB9\u4E0D\u5B8C\u6574" },
|
|
2478
|
+
{ value: "needs_major_changes", label: "\u9700\u8981\u5927\u91CF\u4FEE\u6539" },
|
|
2479
|
+
{ value: "too_slow", label: "\u592A\u6162" },
|
|
2480
|
+
{ value: "other", label: "\u5176\u4ED6" }
|
|
2481
|
+
];
|
|
2482
|
+
function feedbackReasonLabel(reason) {
|
|
2483
|
+
return FEEDBACK_REASONS.find((item) => item.value === reason)?.label ?? null;
|
|
2484
|
+
}
|
|
2485
|
+
function HistoricalResultFeedback({ feedback }) {
|
|
2486
|
+
const label = feedbackReasonLabel(feedback.reason);
|
|
2487
|
+
return /* @__PURE__ */ jsxs11(
|
|
2488
|
+
"section",
|
|
2489
|
+
{
|
|
2490
|
+
"aria-label": "\u5386\u53F2\u7ED3\u679C\u53CD\u9988",
|
|
2491
|
+
className: "mt-3 w-fit max-w-full rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--muted)/0.2)] px-3 py-2 text-xs text-[hsl(var(--muted-foreground))]",
|
|
2492
|
+
children: [
|
|
2493
|
+
/* @__PURE__ */ jsxs11("span", { children: [
|
|
2494
|
+
"\u4F60\u5BF9\u6B64\u8F6E\u7ED3\u679C\u7684\u8BC4\u4EF7\uFF1A",
|
|
2495
|
+
feedback.helpful ? "\u6709\u5E2E\u52A9" : "\u6CA1\u5E2E\u52A9"
|
|
2496
|
+
] }),
|
|
2497
|
+
label ? /* @__PURE__ */ jsxs11("span", { children: [
|
|
2498
|
+
" \xB7 ",
|
|
2499
|
+
label
|
|
2500
|
+
] }) : null
|
|
2501
|
+
]
|
|
2502
|
+
}
|
|
2503
|
+
);
|
|
2504
|
+
}
|
|
2505
|
+
function ResultFeedback({
|
|
2506
|
+
followup,
|
|
2507
|
+
sessionId,
|
|
2508
|
+
isViewer,
|
|
2509
|
+
onInteraction,
|
|
2510
|
+
savedFeedback,
|
|
2511
|
+
onFeedbackSaved
|
|
2512
|
+
}) {
|
|
2513
|
+
const client = useBladeClient();
|
|
2514
|
+
const [saved, setSaved] = useState10(savedFeedback ?? null);
|
|
2515
|
+
const [helpful, setHelpful] = useState10(savedFeedback?.helpful ?? null);
|
|
2516
|
+
const [reason, setReason] = useState10(savedFeedback?.reason ?? null);
|
|
2517
|
+
const [saving, setSaving] = useState10(false);
|
|
2518
|
+
const [saveError, setSaveError] = useState10(false);
|
|
2519
|
+
const reportedShown = useRef6(false);
|
|
2520
|
+
const latestChoice = useRef6(null);
|
|
2521
|
+
const eligible = followup.feedback_eligible === true && Boolean(sessionId) && !isViewer;
|
|
2522
|
+
useEffect6(() => {
|
|
2523
|
+
if (!eligible || reportedShown.current) return;
|
|
2524
|
+
reportedShown.current = true;
|
|
2525
|
+
emitInteraction(onInteraction, {
|
|
2526
|
+
type: "result_feedback_shown",
|
|
2527
|
+
sessionId,
|
|
2528
|
+
assistantEntryId: followup.assistant_entry_id
|
|
2529
|
+
});
|
|
2530
|
+
}, [eligible, followup.assistant_entry_id, onInteraction, sessionId]);
|
|
2531
|
+
useEffect6(() => {
|
|
2532
|
+
if (!savedFeedback || latestChoice.current) return;
|
|
2533
|
+
setSaved(savedFeedback);
|
|
2534
|
+
setHelpful(savedFeedback.helpful);
|
|
2535
|
+
setReason(savedFeedback.reason);
|
|
2536
|
+
}, [savedFeedback]);
|
|
2537
|
+
const submit = useCallback5(
|
|
2538
|
+
async (nextHelpful, nextReason) => {
|
|
2539
|
+
if (!sessionId) return;
|
|
2540
|
+
const choice = { helpful: nextHelpful, reason: nextReason };
|
|
2541
|
+
latestChoice.current = choice;
|
|
2542
|
+
setHelpful(nextHelpful);
|
|
2543
|
+
setReason(nextReason);
|
|
2544
|
+
setSaving(true);
|
|
2545
|
+
setSaveError(false);
|
|
2546
|
+
try {
|
|
2547
|
+
const result = await client.sessions.putResultFeedback(
|
|
2548
|
+
sessionId,
|
|
2549
|
+
followup.assistant_entry_id,
|
|
2550
|
+
choice
|
|
2551
|
+
);
|
|
2552
|
+
if (latestChoice.current !== choice) return;
|
|
2553
|
+
setSaved(result);
|
|
2554
|
+
onFeedbackSaved?.(result);
|
|
2555
|
+
emitInteraction(onInteraction, {
|
|
2556
|
+
type: "result_feedback_submitted",
|
|
2557
|
+
sessionId,
|
|
2558
|
+
assistantEntryId: followup.assistant_entry_id,
|
|
2559
|
+
helpful: result.helpful,
|
|
2560
|
+
reason: result.reason,
|
|
2561
|
+
updatedAt: result.updated_at
|
|
2562
|
+
});
|
|
2563
|
+
} catch {
|
|
2564
|
+
if (latestChoice.current === choice) setSaveError(true);
|
|
2565
|
+
} finally {
|
|
2566
|
+
if (latestChoice.current === choice) setSaving(false);
|
|
2567
|
+
}
|
|
2568
|
+
},
|
|
2569
|
+
[client, followup.assistant_entry_id, onFeedbackSaved, onInteraction, sessionId]
|
|
2570
|
+
);
|
|
2571
|
+
if (!eligible) return null;
|
|
2572
|
+
return /* @__PURE__ */ jsxs11(
|
|
2573
|
+
"section",
|
|
2574
|
+
{
|
|
2575
|
+
"aria-label": "\u7ED3\u679C\u53CD\u9988",
|
|
2576
|
+
className: "flex flex-col gap-2 border-t border-[hsl(var(--border))] pt-3",
|
|
2577
|
+
children: [
|
|
2578
|
+
/* @__PURE__ */ jsx13("div", { className: "text-xs font-medium text-[hsl(var(--muted-foreground))]", children: "\u76EE\u524D\u7684\u6574\u4F53\u7ED3\u679C\u6709\u5E2E\u52A9\u5417\uFF1F" }),
|
|
2579
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex flex-wrap gap-1.5", children: [
|
|
2580
|
+
/* @__PURE__ */ jsx13(
|
|
2581
|
+
"button",
|
|
2582
|
+
{
|
|
2583
|
+
type: "button",
|
|
2584
|
+
"aria-pressed": helpful === true,
|
|
2585
|
+
disabled: saving,
|
|
2586
|
+
onClick: () => void submit(true, null),
|
|
2587
|
+
className: "rounded-lg border border-[hsl(var(--border))] px-2.5 py-1.5 text-xs aria-pressed:bg-[hsl(var(--primary)/0.1)] disabled:opacity-60",
|
|
2588
|
+
children: "\u6709\u5E2E\u52A9"
|
|
2589
|
+
}
|
|
2590
|
+
),
|
|
2591
|
+
/* @__PURE__ */ jsx13(
|
|
2592
|
+
"button",
|
|
2593
|
+
{
|
|
2594
|
+
type: "button",
|
|
2595
|
+
"aria-pressed": helpful === false,
|
|
2596
|
+
disabled: saving,
|
|
2597
|
+
onClick: () => void submit(false, reason),
|
|
2598
|
+
className: "rounded-lg border border-[hsl(var(--border))] px-2.5 py-1.5 text-xs aria-pressed:bg-[hsl(var(--primary)/0.1)] disabled:opacity-60",
|
|
2599
|
+
children: "\u6CA1\u5E2E\u52A9"
|
|
2600
|
+
}
|
|
2601
|
+
)
|
|
2602
|
+
] }),
|
|
2603
|
+
helpful === false ? /* @__PURE__ */ jsx13("div", { className: "flex flex-wrap gap-1.5", "aria-label": "\u6CA1\u5E2E\u52A9\u7684\u4E3B\u8981\u539F\u56E0", children: FEEDBACK_REASONS.map((item) => /* @__PURE__ */ jsx13(
|
|
2604
|
+
"button",
|
|
2605
|
+
{
|
|
2606
|
+
type: "button",
|
|
2607
|
+
"aria-pressed": reason === item.value,
|
|
2608
|
+
disabled: saving,
|
|
2609
|
+
onClick: () => void submit(false, item.value),
|
|
2610
|
+
className: "rounded-full bg-[hsl(var(--muted)/0.62)] px-2.5 py-1 text-[11px] aria-pressed:bg-[hsl(var(--primary)/0.14)] disabled:opacity-60",
|
|
2611
|
+
children: item.label
|
|
2612
|
+
},
|
|
2613
|
+
item.value
|
|
2614
|
+
)) }) : null,
|
|
2615
|
+
saveError ? /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2 text-xs text-[hsl(var(--destructive))]", children: [
|
|
2616
|
+
/* @__PURE__ */ jsx13("span", { children: "\u53CD\u9988\u6682\u672A\u4FDD\u5B58\uFF0C\u53EF\u91CD\u8BD5" }),
|
|
2617
|
+
/* @__PURE__ */ jsx13(
|
|
2618
|
+
"button",
|
|
2619
|
+
{
|
|
2620
|
+
type: "button",
|
|
2621
|
+
className: "underline",
|
|
2622
|
+
onClick: () => {
|
|
2623
|
+
const choice = latestChoice.current;
|
|
2624
|
+
if (choice) void submit(choice.helpful, choice.reason);
|
|
2625
|
+
},
|
|
2626
|
+
children: "\u91CD\u8BD5"
|
|
2627
|
+
}
|
|
2628
|
+
)
|
|
2629
|
+
] }) : saved ? /* @__PURE__ */ jsx13("div", { className: "text-[11px] text-[hsl(var(--muted-foreground))]", children: "\u5DF2\u4FDD\u5B58\uFF0C\u53EF\u968F\u65F6\u4FEE\u6539" }) : null
|
|
2630
|
+
]
|
|
2631
|
+
}
|
|
2632
|
+
);
|
|
2633
|
+
}
|
|
2634
|
+
function PostChatFollowupBlock({
|
|
2635
|
+
followup,
|
|
2636
|
+
sessionId,
|
|
2637
|
+
onSuggestion,
|
|
2638
|
+
isViewer = false,
|
|
2639
|
+
onInteraction,
|
|
2640
|
+
savedFeedback,
|
|
2641
|
+
onFeedbackSaved
|
|
2642
|
+
}) {
|
|
2643
|
+
const [expanded, setExpanded] = useState10(false);
|
|
2644
|
+
const adopted = useRef6(/* @__PURE__ */ new Set());
|
|
2645
|
+
const reportedSuggestions = useRef6(false);
|
|
2646
|
+
const reportedArtifacts = useRef6(/* @__PURE__ */ new Set());
|
|
2647
|
+
const openedArtifacts = useRef6(/* @__PURE__ */ new Set());
|
|
2648
|
+
const artifacts = followup.final_artifacts ?? [];
|
|
2649
|
+
const visibleArtifacts = expanded ? artifacts : artifacts.slice(0, 3);
|
|
2650
|
+
useEffect6(() => {
|
|
2651
|
+
if (!reportedSuggestions.current && followup.suggestions.length > 0) {
|
|
2652
|
+
reportedSuggestions.current = true;
|
|
2653
|
+
emitInteraction(onInteraction, {
|
|
2654
|
+
type: "suggestions_shown",
|
|
2655
|
+
sessionId,
|
|
2656
|
+
assistantEntryId: followup.assistant_entry_id,
|
|
2657
|
+
count: followup.suggestions.length
|
|
2658
|
+
});
|
|
2659
|
+
}
|
|
2660
|
+
for (let artifactIndex = 0; artifactIndex < visibleArtifacts.length; artifactIndex += 1) {
|
|
2661
|
+
if (reportedArtifacts.current.has(artifactIndex)) continue;
|
|
2662
|
+
const artifact = visibleArtifacts[artifactIndex];
|
|
2663
|
+
if (!artifact) continue;
|
|
2664
|
+
reportedArtifacts.current.add(artifactIndex);
|
|
2665
|
+
emitInteraction(onInteraction, {
|
|
2666
|
+
type: "artifact_shown",
|
|
2667
|
+
sessionId,
|
|
2668
|
+
assistantEntryId: followup.assistant_entry_id,
|
|
2669
|
+
artifactIndex,
|
|
2670
|
+
artifactKind: artifact.kind
|
|
2671
|
+
});
|
|
2672
|
+
}
|
|
2673
|
+
}, [
|
|
2674
|
+
followup.assistant_entry_id,
|
|
2675
|
+
followup.suggestions.length,
|
|
2676
|
+
onInteraction,
|
|
2677
|
+
sessionId,
|
|
2678
|
+
visibleArtifacts
|
|
2679
|
+
]);
|
|
2680
|
+
const reportArtifactOpened = useCallback5(
|
|
2681
|
+
(artifactIndex, artifactKind) => {
|
|
2682
|
+
if (openedArtifacts.current.has(artifactIndex)) return;
|
|
2683
|
+
openedArtifacts.current.add(artifactIndex);
|
|
2684
|
+
emitInteraction(onInteraction, {
|
|
2685
|
+
type: "artifact_opened",
|
|
2686
|
+
sessionId,
|
|
2687
|
+
assistantEntryId: followup.assistant_entry_id,
|
|
2688
|
+
artifactIndex,
|
|
2689
|
+
artifactKind
|
|
2690
|
+
});
|
|
2691
|
+
},
|
|
2692
|
+
[followup.assistant_entry_id, onInteraction, sessionId]
|
|
2693
|
+
);
|
|
2694
|
+
if (!followup.recaption && artifacts.length === 0 && followup.suggestions.length === 0 && !followup.feedback_eligible)
|
|
2695
|
+
return null;
|
|
2696
|
+
return /* @__PURE__ */ jsxs11("div", { className: "mt-3 flex w-fit max-w-full flex-col gap-3 rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--muted)/0.28)] p-3 sm:max-w-[680px]", children: [
|
|
2697
|
+
followup.recaption || artifacts.length > 0 ? /* @__PURE__ */ jsxs11("section", { "aria-label": "\u672C\u8F6E\u5C0F\u7ED3", className: "flex flex-col gap-2", children: [
|
|
2698
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-1.5 text-xs font-medium text-[hsl(var(--muted-foreground))]", children: [
|
|
2699
|
+
/* @__PURE__ */ jsx13(Sparkles, { size: 14 }),
|
|
2700
|
+
"\u672C\u8F6E\u5C0F\u7ED3"
|
|
2701
|
+
] }),
|
|
2702
|
+
followup.recaption ? /* @__PURE__ */ jsx13("p", { className: "text-[13px] leading-5", children: followup.recaption }) : null,
|
|
2703
|
+
artifacts.length > 0 ? /* @__PURE__ */ jsxs11(Fragment2, { children: [
|
|
2704
|
+
/* @__PURE__ */ jsx13("div", { className: "grid max-w-full grid-cols-3 gap-1.5", children: visibleArtifacts.map((artifact, artifactIndex) => /* @__PURE__ */ jsx13(
|
|
2705
|
+
ArtifactCard,
|
|
2706
|
+
{
|
|
2707
|
+
artifact,
|
|
2708
|
+
sessionId,
|
|
2709
|
+
assistantEntryId: followup.assistant_entry_id,
|
|
2710
|
+
artifactIndex,
|
|
2711
|
+
onInteraction,
|
|
2712
|
+
onArtifactOpened: reportArtifactOpened
|
|
2713
|
+
},
|
|
2714
|
+
`${artifact.kind}:${artifactIndex}`
|
|
2715
|
+
)) }),
|
|
2716
|
+
artifacts.length > 3 ? /* @__PURE__ */ jsxs11(
|
|
2717
|
+
"button",
|
|
2718
|
+
{
|
|
2719
|
+
type: "button",
|
|
2720
|
+
onClick: () => setExpanded((value) => !value),
|
|
2721
|
+
"aria-expanded": expanded,
|
|
2722
|
+
className: "flex w-fit items-center gap-0.5 text-[11px] text-[hsl(var(--muted-foreground))]",
|
|
2723
|
+
children: [
|
|
2724
|
+
expanded ? "\u6536\u8D77" : `\u5C55\u5F00 ${artifacts.length - 3} \u4E2A`,
|
|
2725
|
+
/* @__PURE__ */ jsx13(ChevronDown, { size: 13, className: expanded ? "rotate-180" : void 0 })
|
|
2726
|
+
]
|
|
2727
|
+
}
|
|
2728
|
+
) : null
|
|
2729
|
+
] }) : null
|
|
2730
|
+
] }) : null,
|
|
2731
|
+
followup.suggestions.length > 0 ? /* @__PURE__ */ jsxs11("section", { "aria-label": "\u4E0B\u4E00\u6B65\u5EFA\u8BAE", className: "flex flex-col gap-1.5", children: [
|
|
2732
|
+
/* @__PURE__ */ jsx13("div", { className: "text-xs font-medium text-[hsl(var(--muted-foreground))]", children: "\u4E0B\u4E00\u6B65\u53EF\u4EE5" }),
|
|
2733
|
+
followup.suggestions.map((suggestion, suggestionIndex) => /* @__PURE__ */ jsxs11(
|
|
2734
|
+
"button",
|
|
2735
|
+
{
|
|
2736
|
+
type: "button",
|
|
2737
|
+
disabled: isViewer,
|
|
2738
|
+
onClick: () => {
|
|
2739
|
+
if (!adopted.current.has(suggestionIndex)) {
|
|
2740
|
+
adopted.current.add(suggestionIndex);
|
|
2741
|
+
emitInteraction(onInteraction, {
|
|
2742
|
+
type: "suggestion_adopted",
|
|
2743
|
+
sessionId,
|
|
2744
|
+
assistantEntryId: followup.assistant_entry_id,
|
|
2745
|
+
suggestionIndex
|
|
2746
|
+
});
|
|
2747
|
+
}
|
|
2748
|
+
onSuggestion?.(suggestion);
|
|
2749
|
+
},
|
|
2750
|
+
className: "group flex items-center gap-2 rounded-xl bg-[hsl(var(--muted)/0.62)] px-3 py-2 text-left text-[13px] disabled:cursor-default disabled:opacity-60",
|
|
2751
|
+
children: [
|
|
2752
|
+
/* @__PURE__ */ jsx13("span", { children: suggestion }),
|
|
2753
|
+
/* @__PURE__ */ jsx13(ArrowRight, { size: 14, className: "ml-auto shrink-0" })
|
|
2754
|
+
]
|
|
2755
|
+
},
|
|
2756
|
+
suggestion
|
|
2757
|
+
))
|
|
2758
|
+
] }) : null,
|
|
2759
|
+
/* @__PURE__ */ jsx13(
|
|
2760
|
+
ResultFeedback,
|
|
2761
|
+
{
|
|
2762
|
+
followup,
|
|
2763
|
+
sessionId,
|
|
2764
|
+
isViewer,
|
|
2765
|
+
onInteraction,
|
|
2766
|
+
savedFeedback,
|
|
2767
|
+
onFeedbackSaved
|
|
2768
|
+
}
|
|
2769
|
+
)
|
|
2770
|
+
] });
|
|
2771
|
+
}
|
|
2772
|
+
|
|
2535
2773
|
// src/components/UserMessageBubble.tsx
|
|
2536
2774
|
import { getFileParts, getImageParts, getTextContent as getTextContent2 } from "@blade-hq/agent-client";
|
|
2537
2775
|
import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
@@ -2617,6 +2855,8 @@ function getMessageResetSignature(messages) {
|
|
|
2617
2855
|
}
|
|
2618
2856
|
function MessageList({
|
|
2619
2857
|
messages,
|
|
2858
|
+
postChatFollowup,
|
|
2859
|
+
onSuggestion,
|
|
2620
2860
|
isStreaming,
|
|
2621
2861
|
sessionStatus,
|
|
2622
2862
|
askAnswers,
|
|
@@ -2624,7 +2864,11 @@ function MessageList({
|
|
|
2624
2864
|
toolCallRenderer,
|
|
2625
2865
|
emptyState,
|
|
2626
2866
|
className,
|
|
2627
|
-
sessionId
|
|
2867
|
+
sessionId,
|
|
2868
|
+
isViewer = false,
|
|
2869
|
+
onFollowupInteraction,
|
|
2870
|
+
resultFeedbackByEntry = /* @__PURE__ */ new Map(),
|
|
2871
|
+
onResultFeedbackSaved
|
|
2628
2872
|
}) {
|
|
2629
2873
|
const renderBlocks = useMemo7(() => {
|
|
2630
2874
|
const visible = messages.filter((message) => {
|
|
@@ -2710,24 +2954,47 @@ function MessageList({
|
|
|
2710
2954
|
return /* @__PURE__ */ jsx15("div", { "data-entry-id": block.message.entry_id, children: isUserMessage(block.message) ? /* @__PURE__ */ jsx15(UserMessageBubble, { message: block.message }) : isErrorMessage(block.message) ? /* @__PURE__ */ jsx15(ErrorMessageBlock, { message: block.message }) : null }, block.key);
|
|
2711
2955
|
}
|
|
2712
2956
|
if (block.type === "assistant_turn") {
|
|
2713
|
-
|
|
2957
|
+
const blockFeedback = block.messages.map(
|
|
2958
|
+
(message) => message.entry_id ? resultFeedbackByEntry.get(message.entry_id) : void 0
|
|
2959
|
+
).find((feedback) => feedback != null);
|
|
2960
|
+
const hasActiveFollowup = Boolean(
|
|
2961
|
+
postChatFollowup && block.messages.some(
|
|
2962
|
+
(message) => message.entry_id === postChatFollowup.assistant_entry_id
|
|
2963
|
+
)
|
|
2964
|
+
);
|
|
2965
|
+
return /* @__PURE__ */ jsx15("div", { "data-entry-id": block.messages[0]?.entry_id, children: /* @__PURE__ */ jsxs13(
|
|
2714
2966
|
RenderErrorBoundary,
|
|
2715
2967
|
{
|
|
2716
2968
|
label: "\u52A9\u624B\u6D88\u606F",
|
|
2717
2969
|
details: block.key,
|
|
2718
2970
|
resetKey: getMessageResetSignature(block.messages),
|
|
2719
|
-
children:
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2971
|
+
children: [
|
|
2972
|
+
/* @__PURE__ */ jsx15(
|
|
2973
|
+
AssistantTurnBlock,
|
|
2974
|
+
{
|
|
2975
|
+
messages: block.messages,
|
|
2976
|
+
isStreaming: block.isStreaming,
|
|
2977
|
+
askAnswers,
|
|
2978
|
+
onAnswer,
|
|
2979
|
+
sessionStatus,
|
|
2980
|
+
toolCallRenderer,
|
|
2981
|
+
sessionId
|
|
2982
|
+
}
|
|
2983
|
+
),
|
|
2984
|
+
blockFeedback && !hasActiveFollowup ? /* @__PURE__ */ jsx15(HistoricalResultFeedback, { feedback: blockFeedback }) : null,
|
|
2985
|
+
hasActiveFollowup && postChatFollowup ? /* @__PURE__ */ jsx15(
|
|
2986
|
+
PostChatFollowupBlock,
|
|
2987
|
+
{
|
|
2988
|
+
followup: postChatFollowup,
|
|
2989
|
+
sessionId,
|
|
2990
|
+
onSuggestion,
|
|
2991
|
+
isViewer,
|
|
2992
|
+
onInteraction: onFollowupInteraction,
|
|
2993
|
+
savedFeedback: blockFeedback,
|
|
2994
|
+
onFeedbackSaved: onResultFeedbackSaved
|
|
2995
|
+
}
|
|
2996
|
+
) : null
|
|
2997
|
+
]
|
|
2731
2998
|
}
|
|
2732
2999
|
) }, block.key);
|
|
2733
3000
|
}
|
|
@@ -2754,8 +3021,8 @@ function MessageList({
|
|
|
2754
3021
|
}
|
|
2755
3022
|
function AutoScrollOnUserSend({ userMessageCount }) {
|
|
2756
3023
|
const { scrollToBottom } = useStickToBottomContext();
|
|
2757
|
-
const previousCountRef =
|
|
2758
|
-
|
|
3024
|
+
const previousCountRef = useRef7(userMessageCount);
|
|
3025
|
+
useEffect7(() => {
|
|
2759
3026
|
if (userMessageCount > previousCountRef.current) {
|
|
2760
3027
|
scrollToBottom("instant");
|
|
2761
3028
|
}
|
|
@@ -2766,8 +3033,8 @@ function AutoScrollOnUserSend({ userMessageCount }) {
|
|
|
2766
3033
|
function ScrollToBottomButton() {
|
|
2767
3034
|
const { isAtBottom, scrollToBottom } = useStickToBottomContext();
|
|
2768
3035
|
const [visible, setVisible] = useState11(false);
|
|
2769
|
-
const hideTimerRef =
|
|
2770
|
-
|
|
3036
|
+
const hideTimerRef = useRef7(null);
|
|
3037
|
+
useEffect7(() => {
|
|
2771
3038
|
if (isAtBottom) {
|
|
2772
3039
|
if (!hideTimerRef.current) {
|
|
2773
3040
|
hideTimerRef.current = setTimeout(() => {
|
|
@@ -2789,7 +3056,7 @@ function ScrollToBottomButton() {
|
|
|
2789
3056
|
}
|
|
2790
3057
|
};
|
|
2791
3058
|
}, [isAtBottom]);
|
|
2792
|
-
const handleClick =
|
|
3059
|
+
const handleClick = useCallback6(() => {
|
|
2793
3060
|
if (hideTimerRef.current) {
|
|
2794
3061
|
clearTimeout(hideTimerRef.current);
|
|
2795
3062
|
hideTimerRef.current = null;
|
|
@@ -2837,16 +3104,22 @@ function ChatSurface({
|
|
|
2837
3104
|
connection,
|
|
2838
3105
|
errorMessage,
|
|
2839
3106
|
messages,
|
|
3107
|
+
postChatFollowup,
|
|
2840
3108
|
isStreaming,
|
|
2841
3109
|
isStopping,
|
|
2842
3110
|
inputText,
|
|
2843
3111
|
onInputChange,
|
|
3112
|
+
onSuggestion,
|
|
2844
3113
|
onSend,
|
|
2845
3114
|
onStop,
|
|
2846
3115
|
sessionStatus,
|
|
2847
3116
|
askAnswers,
|
|
2848
3117
|
onAnswer,
|
|
2849
3118
|
sessionId,
|
|
3119
|
+
isViewer,
|
|
3120
|
+
resultFeedbackByEntry,
|
|
3121
|
+
onResultFeedbackSaved,
|
|
3122
|
+
onFollowupInteraction,
|
|
2850
3123
|
beforeInput,
|
|
2851
3124
|
banner
|
|
2852
3125
|
}) {
|
|
@@ -2870,6 +3143,8 @@ function ChatSurface({
|
|
|
2870
3143
|
MessageList,
|
|
2871
3144
|
{
|
|
2872
3145
|
messages,
|
|
3146
|
+
postChatFollowup,
|
|
3147
|
+
onSuggestion,
|
|
2873
3148
|
isStreaming,
|
|
2874
3149
|
sessionStatus,
|
|
2875
3150
|
askAnswers,
|
|
@@ -2877,7 +3152,11 @@ function ChatSurface({
|
|
|
2877
3152
|
toolCallRenderer: renderers?.toolCall,
|
|
2878
3153
|
emptyState: slots?.emptyState,
|
|
2879
3154
|
className: classNames?.messageList,
|
|
2880
|
-
sessionId
|
|
3155
|
+
sessionId,
|
|
3156
|
+
isViewer,
|
|
3157
|
+
resultFeedbackByEntry,
|
|
3158
|
+
onResultFeedbackSaved,
|
|
3159
|
+
onFollowupInteraction
|
|
2881
3160
|
}
|
|
2882
3161
|
),
|
|
2883
3162
|
beforeInput,
|
|
@@ -2901,7 +3180,7 @@ function ChatSurface({
|
|
|
2901
3180
|
}
|
|
2902
3181
|
|
|
2903
3182
|
// src/components/AgentChat.tsx
|
|
2904
|
-
import { Fragment as
|
|
3183
|
+
import { Fragment as Fragment3, jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2905
3184
|
function isUnauthorizedError(error) {
|
|
2906
3185
|
return error instanceof BladeApiError && error.status === 401;
|
|
2907
3186
|
}
|
|
@@ -2973,8 +3252,10 @@ function ChatSessionView({
|
|
|
2973
3252
|
slots,
|
|
2974
3253
|
placeholder,
|
|
2975
3254
|
theme,
|
|
3255
|
+
onFollowupInteraction,
|
|
2976
3256
|
onUnauthorized
|
|
2977
3257
|
}) {
|
|
3258
|
+
const client = useBladeClient();
|
|
2978
3259
|
const { session, state, error } = useAgentSession(sessionId, {
|
|
2979
3260
|
createOptions,
|
|
2980
3261
|
onSessionCreated
|
|
@@ -2982,12 +3263,50 @@ function ChatSessionView({
|
|
|
2982
3263
|
const replay = useReplay(session);
|
|
2983
3264
|
const [stopRequested, setStopRequested] = useState12(false);
|
|
2984
3265
|
const [inputText, setInputText] = useState12("");
|
|
2985
|
-
|
|
3266
|
+
const [resultFeedback, setResultFeedback] = useState12([]);
|
|
3267
|
+
const resolvedSessionId = session?.sessionId;
|
|
3268
|
+
const isViewer = state?.viewerRole === "viewer";
|
|
3269
|
+
useEffect8(() => {
|
|
3270
|
+
setResultFeedback([]);
|
|
3271
|
+
if (!resolvedSessionId || isViewer) return;
|
|
3272
|
+
let cancelled = false;
|
|
3273
|
+
void client.sessions.listResultFeedback(resolvedSessionId).then(
|
|
3274
|
+
(items) => {
|
|
3275
|
+
if (cancelled) return;
|
|
3276
|
+
setResultFeedback((current) => {
|
|
3277
|
+
const merged = new Map(items.map((item) => [item.assistant_entry_id, item]));
|
|
3278
|
+
for (const item of current) {
|
|
3279
|
+
const fetched = merged.get(item.assistant_entry_id);
|
|
3280
|
+
if (!fetched || fetched.updated_at < item.updated_at) {
|
|
3281
|
+
merged.set(item.assistant_entry_id, item);
|
|
3282
|
+
}
|
|
3283
|
+
}
|
|
3284
|
+
return [...merged.values()];
|
|
3285
|
+
});
|
|
3286
|
+
},
|
|
3287
|
+
() => {
|
|
3288
|
+
}
|
|
3289
|
+
);
|
|
3290
|
+
return () => {
|
|
3291
|
+
cancelled = true;
|
|
3292
|
+
};
|
|
3293
|
+
}, [client, isViewer, resolvedSessionId]);
|
|
3294
|
+
const resultFeedbackByEntry = useMemo8(
|
|
3295
|
+
() => new Map(resultFeedback.map((item) => [item.assistant_entry_id, item])),
|
|
3296
|
+
[resultFeedback]
|
|
3297
|
+
);
|
|
3298
|
+
const handleResultFeedbackSaved = useCallback7((saved) => {
|
|
3299
|
+
setResultFeedback((current) => [
|
|
3300
|
+
...current.filter((item) => item.assistant_entry_id !== saved.assistant_entry_id),
|
|
3301
|
+
saved
|
|
3302
|
+
]);
|
|
3303
|
+
}, []);
|
|
3304
|
+
useEffect8(() => {
|
|
2986
3305
|
if (session) {
|
|
2987
3306
|
onSessionReady?.(session);
|
|
2988
3307
|
}
|
|
2989
3308
|
}, [session, onSessionReady]);
|
|
2990
|
-
|
|
3309
|
+
useEffect8(() => {
|
|
2991
3310
|
if (!session) return;
|
|
2992
3311
|
const offAttach = session.on("attachRequested", ({ label, content }) => {
|
|
2993
3312
|
setInputText((prev) => `${prev ? `${prev}
|
|
@@ -3003,12 +3322,12 @@ ${content}`);
|
|
|
3003
3322
|
offInsert();
|
|
3004
3323
|
};
|
|
3005
3324
|
}, [session]);
|
|
3006
|
-
|
|
3325
|
+
useEffect8(() => {
|
|
3007
3326
|
if (isUnauthorizedError(error)) {
|
|
3008
3327
|
onUnauthorized();
|
|
3009
3328
|
}
|
|
3010
3329
|
}, [error, onUnauthorized]);
|
|
3011
|
-
|
|
3330
|
+
useEffect8(() => {
|
|
3012
3331
|
if (!session || !commands) return;
|
|
3013
3332
|
const unsubscribes = Object.entries(commands).map(
|
|
3014
3333
|
([action, handler]) => session.onCommand(action, (payload) => handler(payload))
|
|
@@ -3033,12 +3352,13 @@ ${content}`);
|
|
|
3033
3352
|
ChatSurface,
|
|
3034
3353
|
{
|
|
3035
3354
|
theme,
|
|
3355
|
+
onFollowupInteraction,
|
|
3036
3356
|
classNames,
|
|
3037
3357
|
renderers,
|
|
3038
3358
|
slots,
|
|
3039
3359
|
placeholder,
|
|
3040
3360
|
connection: state?.connection ?? "connecting",
|
|
3041
|
-
banner: /* @__PURE__ */ jsxs15(
|
|
3361
|
+
banner: /* @__PURE__ */ jsxs15(Fragment3, { children: [
|
|
3042
3362
|
/* @__PURE__ */ jsx17(
|
|
3043
3363
|
ReplayBar,
|
|
3044
3364
|
{
|
|
@@ -3053,10 +3373,14 @@ ${content}`);
|
|
|
3053
3373
|
] }),
|
|
3054
3374
|
errorMessage,
|
|
3055
3375
|
messages: state?.messages ?? [],
|
|
3376
|
+
postChatFollowup: latestPostChatFollowup(state?.turns ?? []),
|
|
3377
|
+
resultFeedbackByEntry,
|
|
3378
|
+
onResultFeedbackSaved: handleResultFeedbackSaved,
|
|
3056
3379
|
isStreaming,
|
|
3057
3380
|
isStopping,
|
|
3058
3381
|
inputText,
|
|
3059
3382
|
onInputChange: setInputText,
|
|
3383
|
+
onSuggestion: setInputText,
|
|
3060
3384
|
onSend: handleSend,
|
|
3061
3385
|
onStop: handleStop,
|
|
3062
3386
|
sessionStatus: state?.status ?? void 0,
|
|
@@ -3067,13 +3391,14 @@ ${content}`);
|
|
|
3067
3391
|
askUserAnswer: { tool_call_id: toolCallId, ...answerData }
|
|
3068
3392
|
});
|
|
3069
3393
|
},
|
|
3070
|
-
sessionId:
|
|
3394
|
+
sessionId: resolvedSessionId,
|
|
3395
|
+
isViewer
|
|
3071
3396
|
}
|
|
3072
3397
|
);
|
|
3073
3398
|
}
|
|
3074
3399
|
|
|
3075
3400
|
// src/components/LlmChat.tsx
|
|
3076
|
-
import { useEffect as
|
|
3401
|
+
import { useEffect as useEffect9, useMemo as useMemo9, useState as useState14 } from "react";
|
|
3077
3402
|
|
|
3078
3403
|
// src/components/LlmAdvancedSettings.tsx
|
|
3079
3404
|
import { useState as useState13 } from "react";
|
|
@@ -3212,7 +3537,7 @@ function LlmChat({
|
|
|
3212
3537
|
const { messages, isStreaming, error, send, stop, reset } = useLlmChat(effective);
|
|
3213
3538
|
const [inputText, setInputText] = useState14("");
|
|
3214
3539
|
const [stopRequested, setStopRequested] = useState14(false);
|
|
3215
|
-
const handle =
|
|
3540
|
+
const handle = useMemo9(
|
|
3216
3541
|
() => ({
|
|
3217
3542
|
insertText: (text) => setInputText((prev) => prev ? `${prev}
|
|
3218
3543
|
${text}` : text),
|
|
@@ -3221,7 +3546,7 @@ ${text}` : text),
|
|
|
3221
3546
|
}),
|
|
3222
3547
|
[send, reset]
|
|
3223
3548
|
);
|
|
3224
|
-
|
|
3549
|
+
useEffect9(() => {
|
|
3225
3550
|
onReady?.(handle);
|
|
3226
3551
|
}, [handle, onReady]);
|
|
3227
3552
|
return /* @__PURE__ */ jsx19(
|
|
@@ -3311,7 +3636,8 @@ lucide-react/dist/esm/shared/src/utils.js:
|
|
|
3311
3636
|
lucide-react/dist/esm/defaultAttributes.js:
|
|
3312
3637
|
lucide-react/dist/esm/Icon.js:
|
|
3313
3638
|
lucide-react/dist/esm/createLucideIcon.js:
|
|
3314
|
-
lucide-react/dist/esm/icons/
|
|
3639
|
+
lucide-react/dist/esm/icons/arrow-right.js:
|
|
3640
|
+
lucide-react/dist/esm/icons/arrow-up-right.js:
|
|
3315
3641
|
lucide-react/dist/esm/icons/arrow-up.js:
|
|
3316
3642
|
lucide-react/dist/esm/icons/bot.js:
|
|
3317
3643
|
lucide-react/dist/esm/icons/brain.js:
|
|
@@ -3321,21 +3647,19 @@ lucide-react/dist/esm/icons/chevron-right.js:
|
|
|
3321
3647
|
lucide-react/dist/esm/icons/circle-alert.js:
|
|
3322
3648
|
lucide-react/dist/esm/icons/copy.js:
|
|
3323
3649
|
lucide-react/dist/esm/icons/download.js:
|
|
3324
|
-
lucide-react/dist/esm/icons/file-code-2.js:
|
|
3325
|
-
lucide-react/dist/esm/icons/file-spreadsheet.js:
|
|
3326
3650
|
lucide-react/dist/esm/icons/file-text.js:
|
|
3327
3651
|
lucide-react/dist/esm/icons/file.js:
|
|
3328
3652
|
lucide-react/dist/esm/icons/film.js:
|
|
3329
|
-
lucide-react/dist/esm/icons/
|
|
3653
|
+
lucide-react/dist/esm/icons/globe.js:
|
|
3330
3654
|
lucide-react/dist/esm/icons/layers.js:
|
|
3331
3655
|
lucide-react/dist/esm/icons/lightbulb.js:
|
|
3332
3656
|
lucide-react/dist/esm/icons/loader-circle.js:
|
|
3333
3657
|
lucide-react/dist/esm/icons/lock-keyhole.js:
|
|
3334
3658
|
lucide-react/dist/esm/icons/message-square-more.js:
|
|
3335
3659
|
lucide-react/dist/esm/icons/message-square.js:
|
|
3336
|
-
lucide-react/dist/esm/icons/music.js:
|
|
3337
3660
|
lucide-react/dist/esm/icons/play.js:
|
|
3338
3661
|
lucide-react/dist/esm/icons/settings-2.js:
|
|
3662
|
+
lucide-react/dist/esm/icons/sparkles.js:
|
|
3339
3663
|
lucide-react/dist/esm/icons/square.js:
|
|
3340
3664
|
lucide-react/dist/esm/icons/triangle-alert.js:
|
|
3341
3665
|
lucide-react/dist/esm/icons/x.js:
|