@malette/agent-sdk 0.1.3-beta.11 → 0.1.3-beta.13
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.js +854 -116
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +855 -117
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +11 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -499,10 +499,16 @@ var artifactService = {
|
|
|
499
499
|
/**
|
|
500
500
|
* 更新产物内容(用户编辑后保存)
|
|
501
501
|
*/
|
|
502
|
-
updateContent: async (artifactId, content) => {
|
|
502
|
+
updateContent: async (artifactId, content, options) => {
|
|
503
503
|
return fetcher(`${API_BASE}/artifacts/${artifactId}/content`, {
|
|
504
504
|
method: "PUT",
|
|
505
|
-
body: JSON.stringify({
|
|
505
|
+
body: JSON.stringify({
|
|
506
|
+
artifactId,
|
|
507
|
+
content,
|
|
508
|
+
...options?.type && { type: options.type },
|
|
509
|
+
...options?.language !== void 0 && { language: options.language },
|
|
510
|
+
...options?.title !== void 0 && { title: options.title }
|
|
511
|
+
})
|
|
506
512
|
});
|
|
507
513
|
},
|
|
508
514
|
/**
|
|
@@ -1707,6 +1713,25 @@ var useAgentStore = zustand.create()(
|
|
|
1707
1713
|
false,
|
|
1708
1714
|
"updateArtifactVisibility"
|
|
1709
1715
|
),
|
|
1716
|
+
updateArtifactType: (artifactId, type, language) => set(
|
|
1717
|
+
(state) => {
|
|
1718
|
+
const existing = state.artifacts[artifactId];
|
|
1719
|
+
if (!existing) return state;
|
|
1720
|
+
return {
|
|
1721
|
+
artifacts: {
|
|
1722
|
+
...state.artifacts,
|
|
1723
|
+
[artifactId]: {
|
|
1724
|
+
...existing,
|
|
1725
|
+
type,
|
|
1726
|
+
language: language ?? existing.language,
|
|
1727
|
+
gmtModified: (/* @__PURE__ */ new Date()).toISOString()
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1730
|
+
};
|
|
1731
|
+
},
|
|
1732
|
+
false,
|
|
1733
|
+
"updateArtifactType"
|
|
1734
|
+
),
|
|
1710
1735
|
// ============ 复合操作 ============
|
|
1711
1736
|
startNewChat: (sessionId) => {
|
|
1712
1737
|
set(
|
|
@@ -7809,6 +7834,104 @@ var resolveAssetForDisplay = async (asset, config) => {
|
|
|
7809
7834
|
}
|
|
7810
7835
|
return null;
|
|
7811
7836
|
};
|
|
7837
|
+
var resolveHtmlAssetUrls = (html2) => {
|
|
7838
|
+
const origin = typeof window !== "undefined" ? window.location.origin : "";
|
|
7839
|
+
const resolveSrc = (src, isVideo) => {
|
|
7840
|
+
if (!src.trim()) return src;
|
|
7841
|
+
if (/^(data:|blob:|javascript:|#)/i.test(src)) return src;
|
|
7842
|
+
if (src.includes("${")) return src;
|
|
7843
|
+
if (/^https?:/i.test(src)) {
|
|
7844
|
+
if (src.includes("industryai")) {
|
|
7845
|
+
return src.split("?")[0];
|
|
7846
|
+
}
|
|
7847
|
+
return src;
|
|
7848
|
+
}
|
|
7849
|
+
const resolved = isVideo ? getHDImageUrl(src) : getImageUrl(src);
|
|
7850
|
+
return resolved.startsWith("http") ? resolved : `${origin}${resolved}`;
|
|
7851
|
+
};
|
|
7852
|
+
const processHtmlPart = (part) => {
|
|
7853
|
+
let result = part.replace(
|
|
7854
|
+
/(<(?:img|video|source)\s[^>]*?\bsrc\s*=\s*["'])([^"']*)(["'])/gi,
|
|
7855
|
+
(match, prefix, src, suffix) => {
|
|
7856
|
+
const tagMatch = match.match(/^<(\w+)/i);
|
|
7857
|
+
const tag = tagMatch?.[1]?.toLowerCase() ?? "";
|
|
7858
|
+
const isVideo = tag === "video" || tag === "source";
|
|
7859
|
+
return `${prefix}${resolveSrc(src, isVideo)}${suffix}`;
|
|
7860
|
+
}
|
|
7861
|
+
);
|
|
7862
|
+
result = result.replace(
|
|
7863
|
+
/(<video\s[^>]*?\bposter\s*=\s*["'])([^"']*)(["'])/gi,
|
|
7864
|
+
(match, prefix, src, suffix) => `${prefix}${resolveSrc(src, false)}${suffix}`
|
|
7865
|
+
);
|
|
7866
|
+
return result;
|
|
7867
|
+
};
|
|
7868
|
+
const parts = html2.split(/(<script\b[\s\S]*?<\/script>)/gi);
|
|
7869
|
+
return parts.map((part, i) => i % 2 === 1 ? part : processHtmlPart(part)).join("");
|
|
7870
|
+
};
|
|
7871
|
+
var resolveHtmlAssetUrlsAsync = async (html2, config) => {
|
|
7872
|
+
if (!config?.asset) return resolveHtmlAssetUrls(html2);
|
|
7873
|
+
const srcPattern = /(<(?:img|video|source)\s[^>]*?\bsrc\s*=\s*["'])([^"']*)(["'])/gi;
|
|
7874
|
+
const posterPattern = /(<video\s[^>]*?\bposter\s*=\s*["'])([^"']*)(["'])/gi;
|
|
7875
|
+
const scriptSplitPattern = /(<script\b[\s\S]*?<\/script>)/gi;
|
|
7876
|
+
const parts = html2.split(scriptSplitPattern);
|
|
7877
|
+
const nonScriptHtml = parts.filter((_, i) => i % 2 === 0).join("");
|
|
7878
|
+
const urlsToResolve = /* @__PURE__ */ new Map();
|
|
7879
|
+
const collectUrl = (src) => {
|
|
7880
|
+
if (!src.trim()) return;
|
|
7881
|
+
if (/^(data:|blob:|javascript:|#)/i.test(src)) return;
|
|
7882
|
+
if (src.includes("${")) return;
|
|
7883
|
+
urlsToResolve.set(src, src);
|
|
7884
|
+
};
|
|
7885
|
+
let match;
|
|
7886
|
+
const srcRe = new RegExp(srcPattern.source, srcPattern.flags);
|
|
7887
|
+
while ((match = srcRe.exec(nonScriptHtml)) !== null) {
|
|
7888
|
+
collectUrl(match[2]);
|
|
7889
|
+
}
|
|
7890
|
+
const posterRe = new RegExp(posterPattern.source, posterPattern.flags);
|
|
7891
|
+
while ((match = posterRe.exec(nonScriptHtml)) !== null) {
|
|
7892
|
+
collectUrl(match[2]);
|
|
7893
|
+
}
|
|
7894
|
+
await Promise.all(
|
|
7895
|
+
Array.from(urlsToResolve.keys()).map(async (src) => {
|
|
7896
|
+
const tagMatch = nonScriptHtml.match(
|
|
7897
|
+
new RegExp(`<(img|video|source)[^>]*(?:src|poster)=["']${src.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}["']`, "i")
|
|
7898
|
+
);
|
|
7899
|
+
const tag = tagMatch?.[1]?.toLowerCase() ?? "";
|
|
7900
|
+
const isVideo = tag === "video" || tag === "source";
|
|
7901
|
+
const type = isVideo ? "video" : "image";
|
|
7902
|
+
const isHttp = /^https?:/i.test(src);
|
|
7903
|
+
const asset = createAssetFromSource({
|
|
7904
|
+
fileId: !isHttp ? src : void 0,
|
|
7905
|
+
fileUrl: isHttp ? src : void 0,
|
|
7906
|
+
type
|
|
7907
|
+
});
|
|
7908
|
+
if (!asset) return;
|
|
7909
|
+
const resolved = await resolveAssetForDisplay(asset, config);
|
|
7910
|
+
if (resolved) {
|
|
7911
|
+
urlsToResolve.set(src, resolved.url);
|
|
7912
|
+
}
|
|
7913
|
+
})
|
|
7914
|
+
);
|
|
7915
|
+
const processedParts = parts.map((part, i) => {
|
|
7916
|
+
if (i % 2 === 1) return part;
|
|
7917
|
+
let result = part.replace(
|
|
7918
|
+
/(<(?:img|video|source)\s[^>]*?\bsrc\s*=\s*["'])([^"']*)(["'])/gi,
|
|
7919
|
+
(m, prefix, src, suffix) => {
|
|
7920
|
+
const resolved = urlsToResolve.get(src);
|
|
7921
|
+
return resolved && resolved !== src ? `${prefix}${resolved}${suffix}` : m;
|
|
7922
|
+
}
|
|
7923
|
+
);
|
|
7924
|
+
result = result.replace(
|
|
7925
|
+
/(<video\s[^>]*?\bposter\s*=\s*["'])([^"']*)(["'])/gi,
|
|
7926
|
+
(m, prefix, src, suffix) => {
|
|
7927
|
+
const resolved = urlsToResolve.get(src);
|
|
7928
|
+
return resolved && resolved !== src ? `${prefix}${resolved}${suffix}` : m;
|
|
7929
|
+
}
|
|
7930
|
+
);
|
|
7931
|
+
return result;
|
|
7932
|
+
});
|
|
7933
|
+
return processedParts.join("");
|
|
7934
|
+
};
|
|
7812
7935
|
var ComponentContext = React16.createContext(void 0);
|
|
7813
7936
|
var ComponentProvider = ({
|
|
7814
7937
|
components = {},
|
|
@@ -16260,10 +16383,10 @@ var Observer = class {
|
|
|
16260
16383
|
});
|
|
16261
16384
|
}
|
|
16262
16385
|
};
|
|
16263
|
-
this.custom = (
|
|
16386
|
+
this.custom = (jsx68, data) => {
|
|
16264
16387
|
const id = (data == null ? void 0 : data.id) || toastsCounter++;
|
|
16265
16388
|
this.create({
|
|
16266
|
-
jsx:
|
|
16389
|
+
jsx: jsx68(id),
|
|
16267
16390
|
id,
|
|
16268
16391
|
...data
|
|
16269
16392
|
});
|
|
@@ -21772,15 +21895,24 @@ var CodeBlock3 = React16.memo(function CodeBlock4({
|
|
|
21772
21895
|
] }, i)) }) }) })
|
|
21773
21896
|
] });
|
|
21774
21897
|
});
|
|
21775
|
-
var HtmlPreview3 = React16.memo(function HtmlPreview4({
|
|
21898
|
+
var HtmlPreview3 = React16.memo(function HtmlPreview4({
|
|
21899
|
+
content,
|
|
21900
|
+
config
|
|
21901
|
+
}) {
|
|
21776
21902
|
const [scale, setScale] = React16.useState(1);
|
|
21777
21903
|
const [deviceMode, setDeviceMode] = React16.useState("responsive");
|
|
21778
21904
|
const [isLoading, setIsLoading] = React16.useState(true);
|
|
21779
21905
|
const [iframeHeight, setIframeHeight] = React16.useState(600);
|
|
21780
21906
|
const iframeRef = React16.useRef(null);
|
|
21781
21907
|
const containerRef = React16.useRef(null);
|
|
21782
|
-
const blobUrl = React16.
|
|
21783
|
-
|
|
21908
|
+
const [blobUrl, setBlobUrl] = React16.useState("");
|
|
21909
|
+
React16.useEffect(() => {
|
|
21910
|
+
let active = true;
|
|
21911
|
+
let currentUrl = "";
|
|
21912
|
+
const buildBlobUrl = async () => {
|
|
21913
|
+
const processed = config?.asset ? await resolveHtmlAssetUrlsAsync(content, config) : resolveHtmlAssetUrls(content);
|
|
21914
|
+
if (!active) return;
|
|
21915
|
+
const styleInjection = `
|
|
21784
21916
|
<style>
|
|
21785
21917
|
html, body {
|
|
21786
21918
|
margin: 0;
|
|
@@ -21794,24 +21926,26 @@ var HtmlPreview3 = React16.memo(function HtmlPreview4({ content }) {
|
|
|
21794
21926
|
}
|
|
21795
21927
|
</style>
|
|
21796
21928
|
`;
|
|
21797
|
-
|
|
21798
|
-
|
|
21799
|
-
|
|
21800
|
-
|
|
21801
|
-
|
|
21802
|
-
|
|
21803
|
-
|
|
21804
|
-
|
|
21805
|
-
|
|
21806
|
-
|
|
21807
|
-
|
|
21808
|
-
|
|
21809
|
-
|
|
21810
|
-
|
|
21929
|
+
let modifiedContent = processed;
|
|
21930
|
+
if (processed.includes("<head>")) {
|
|
21931
|
+
modifiedContent = processed.replace("<head>", "<head>" + styleInjection);
|
|
21932
|
+
} else if (processed.includes("<html>")) {
|
|
21933
|
+
modifiedContent = processed.replace("<html>", "<html><head>" + styleInjection + "</head>");
|
|
21934
|
+
} else if (processed.includes("<!DOCTYPE") || processed.includes("<!doctype")) {
|
|
21935
|
+
modifiedContent = processed.replace(/(<!DOCTYPE[^>]*>|<!doctype[^>]*>)/i, "$1<html><head>" + styleInjection + "</head><body>") + "</body></html>";
|
|
21936
|
+
} else {
|
|
21937
|
+
modifiedContent = `<!DOCTYPE html><html><head>${styleInjection}</head><body>${processed}</body></html>`;
|
|
21938
|
+
}
|
|
21939
|
+
const blob = new Blob([modifiedContent], { type: "text/html" });
|
|
21940
|
+
currentUrl = URL.createObjectURL(blob);
|
|
21941
|
+
setBlobUrl(currentUrl);
|
|
21942
|
+
};
|
|
21943
|
+
buildBlobUrl();
|
|
21811
21944
|
return () => {
|
|
21812
|
-
|
|
21945
|
+
active = false;
|
|
21946
|
+
if (currentUrl) URL.revokeObjectURL(currentUrl);
|
|
21813
21947
|
};
|
|
21814
|
-
}, [
|
|
21948
|
+
}, [content, config]);
|
|
21815
21949
|
const deviceConfig = {
|
|
21816
21950
|
desktop: { width: "100%", maxWidth: "1400px", height: 800, icon: lucideReact.Monitor, label: "Desktop" },
|
|
21817
21951
|
tablet: { width: "768px", height: 1024, icon: lucideReact.Tablet, label: "Tablet" },
|
|
@@ -21966,7 +22100,7 @@ var HtmlPreview3 = React16.memo(function HtmlPreview4({ content }) {
|
|
|
21966
22100
|
},
|
|
21967
22101
|
children: [
|
|
21968
22102
|
deviceMode === "mobile" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-6 bg-zinc-900 agent-sdk-light:bg-zinc-200 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-16 h-4 bg-zinc-800 agent-sdk-light:bg-zinc-300 rounded-full" }) }),
|
|
21969
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
22103
|
+
blobUrl && /* @__PURE__ */ jsxRuntime.jsx(
|
|
21970
22104
|
"iframe",
|
|
21971
22105
|
{
|
|
21972
22106
|
ref: iframeRef,
|
|
@@ -23863,6 +23997,237 @@ function ArtifactDeleteButton({
|
|
|
23863
23997
|
modal
|
|
23864
23998
|
] });
|
|
23865
23999
|
}
|
|
24000
|
+
var CHANGEABLE_TYPES = ["code", "html", "svg", "markdown", "json", "text"];
|
|
24001
|
+
function ArtifactTypeSelector({
|
|
24002
|
+
currentType,
|
|
24003
|
+
currentLanguage,
|
|
24004
|
+
onTypeChange,
|
|
24005
|
+
disabled = false
|
|
24006
|
+
}) {
|
|
24007
|
+
const [isOpen, setIsOpen] = React16.useState(false);
|
|
24008
|
+
const [isChanging, setIsChanging] = React16.useState(false);
|
|
24009
|
+
const dropdownRef = React16.useRef(null);
|
|
24010
|
+
const typeConfig2 = artifactTypeConfig[currentType] || artifactTypeConfig.text;
|
|
24011
|
+
const isChangeable = CHANGEABLE_TYPES.includes(currentType);
|
|
24012
|
+
React16.useEffect(() => {
|
|
24013
|
+
if (!isOpen) return;
|
|
24014
|
+
const handleClickOutside = (e) => {
|
|
24015
|
+
if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
|
|
24016
|
+
setIsOpen(false);
|
|
24017
|
+
}
|
|
24018
|
+
};
|
|
24019
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
24020
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
24021
|
+
}, [isOpen]);
|
|
24022
|
+
const handleSelectType = React16.useCallback(async (newType) => {
|
|
24023
|
+
if (newType === currentType || isChanging) return;
|
|
24024
|
+
setIsChanging(true);
|
|
24025
|
+
try {
|
|
24026
|
+
await onTypeChange(newType);
|
|
24027
|
+
setIsOpen(false);
|
|
24028
|
+
} finally {
|
|
24029
|
+
setIsChanging(false);
|
|
24030
|
+
}
|
|
24031
|
+
}, [currentType, isChanging, onTypeChange]);
|
|
24032
|
+
if (!isChangeable) {
|
|
24033
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-7 h-7 rounded-lg ${typeConfig2.bgColor} flex items-center justify-center flex-shrink-0`, children: /* @__PURE__ */ jsxRuntime.jsx(typeConfig2.icon, { size: 14, className: typeConfig2.color }) });
|
|
24034
|
+
}
|
|
24035
|
+
const availableTypes = CHANGEABLE_TYPES.filter((t) => t !== currentType);
|
|
24036
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", ref: dropdownRef, children: [
|
|
24037
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
24038
|
+
"button",
|
|
24039
|
+
{
|
|
24040
|
+
onClick: () => !disabled && !isChanging && setIsOpen(!isOpen),
|
|
24041
|
+
disabled: disabled || isChanging,
|
|
24042
|
+
className: cn3(
|
|
24043
|
+
"flex items-center gap-1 p-1 rounded-lg transition-colors",
|
|
24044
|
+
"hover:bg-zinc-800 agent-sdk-light:hover:bg-zinc-200",
|
|
24045
|
+
(disabled || isChanging) && "opacity-50 cursor-not-allowed"
|
|
24046
|
+
),
|
|
24047
|
+
title: "\u5207\u6362\u4EA7\u7269\u7C7B\u578B",
|
|
24048
|
+
children: [
|
|
24049
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-7 h-7 rounded-lg ${typeConfig2.bgColor} flex items-center justify-center flex-shrink-0`, children: isChanging ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 14, className: `${typeConfig2.color} animate-spin` }) : /* @__PURE__ */ jsxRuntime.jsx(typeConfig2.icon, { size: 14, className: typeConfig2.color }) }),
|
|
24050
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { size: 10, className: "text-zinc-500" })
|
|
24051
|
+
]
|
|
24052
|
+
}
|
|
24053
|
+
),
|
|
24054
|
+
isOpen && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute left-0 top-full mt-1 z-50 w-44 bg-zinc-900 agent-sdk-light:bg-white border border-zinc-700/50 agent-sdk-light:border-zinc-200 rounded-lg shadow-xl overflow-hidden", children: [
|
|
24055
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-2 border-b border-zinc-800/50 agent-sdk-light:border-zinc-100", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] font-medium text-zinc-500 agent-sdk-light:text-zinc-400", children: "\u5207\u6362\u7C7B\u578B" }) }),
|
|
24056
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-1", children: availableTypes.map((type) => {
|
|
24057
|
+
const config = artifactTypeConfig[type];
|
|
24058
|
+
const TypeIcon = config.icon;
|
|
24059
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
24060
|
+
"button",
|
|
24061
|
+
{
|
|
24062
|
+
onClick: () => handleSelectType(type),
|
|
24063
|
+
disabled: isChanging,
|
|
24064
|
+
className: cn3(
|
|
24065
|
+
"flex items-center gap-2.5 px-2 py-1.5 text-xs rounded-md transition-all w-full text-left",
|
|
24066
|
+
"text-zinc-300 agent-sdk-light:text-zinc-700",
|
|
24067
|
+
"hover:bg-zinc-800/70 agent-sdk-light:hover:bg-zinc-100",
|
|
24068
|
+
isChanging && "opacity-50 cursor-not-allowed"
|
|
24069
|
+
),
|
|
24070
|
+
children: [
|
|
24071
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: cn3("w-5 h-5 rounded flex items-center justify-center flex-shrink-0", config.bgColor), children: /* @__PURE__ */ jsxRuntime.jsx(TypeIcon, { size: 11, className: config.color }) }),
|
|
24072
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: config.label })
|
|
24073
|
+
]
|
|
24074
|
+
},
|
|
24075
|
+
type
|
|
24076
|
+
);
|
|
24077
|
+
}) })
|
|
24078
|
+
] })
|
|
24079
|
+
] });
|
|
24080
|
+
}
|
|
24081
|
+
var COMMON_LANGUAGES = [
|
|
24082
|
+
"javascript",
|
|
24083
|
+
"typescript",
|
|
24084
|
+
"python",
|
|
24085
|
+
"java",
|
|
24086
|
+
"go",
|
|
24087
|
+
"rust",
|
|
24088
|
+
"c",
|
|
24089
|
+
"cpp",
|
|
24090
|
+
"csharp",
|
|
24091
|
+
"ruby",
|
|
24092
|
+
"php",
|
|
24093
|
+
"swift",
|
|
24094
|
+
"kotlin",
|
|
24095
|
+
"sql",
|
|
24096
|
+
"shell",
|
|
24097
|
+
"html",
|
|
24098
|
+
"css",
|
|
24099
|
+
"json",
|
|
24100
|
+
"yaml",
|
|
24101
|
+
"xml",
|
|
24102
|
+
"markdown"
|
|
24103
|
+
];
|
|
24104
|
+
function ArtifactLanguageSelector({
|
|
24105
|
+
currentLanguage,
|
|
24106
|
+
onLanguageChange,
|
|
24107
|
+
disabled = false
|
|
24108
|
+
}) {
|
|
24109
|
+
const [isOpen, setIsOpen] = React16.useState(false);
|
|
24110
|
+
const [isChanging, setIsChanging] = React16.useState(false);
|
|
24111
|
+
const [search, setSearch] = React16.useState("");
|
|
24112
|
+
const dropdownRef = React16.useRef(null);
|
|
24113
|
+
const inputRef = React16.useRef(null);
|
|
24114
|
+
React16.useEffect(() => {
|
|
24115
|
+
if (!isOpen) return;
|
|
24116
|
+
const handleClickOutside = (e) => {
|
|
24117
|
+
if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
|
|
24118
|
+
setIsOpen(false);
|
|
24119
|
+
setSearch("");
|
|
24120
|
+
}
|
|
24121
|
+
};
|
|
24122
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
24123
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
24124
|
+
}, [isOpen]);
|
|
24125
|
+
React16.useEffect(() => {
|
|
24126
|
+
if (isOpen && inputRef.current) {
|
|
24127
|
+
inputRef.current.focus();
|
|
24128
|
+
}
|
|
24129
|
+
}, [isOpen]);
|
|
24130
|
+
const handleSelect = React16.useCallback(async (language) => {
|
|
24131
|
+
if (language === currentLanguage || isChanging) return;
|
|
24132
|
+
setIsChanging(true);
|
|
24133
|
+
try {
|
|
24134
|
+
await onLanguageChange(language);
|
|
24135
|
+
setIsOpen(false);
|
|
24136
|
+
setSearch("");
|
|
24137
|
+
} finally {
|
|
24138
|
+
setIsChanging(false);
|
|
24139
|
+
}
|
|
24140
|
+
}, [currentLanguage, isChanging, onLanguageChange]);
|
|
24141
|
+
const handleKeyDown = React16.useCallback((e) => {
|
|
24142
|
+
if (e.key === "Enter" && search.trim()) {
|
|
24143
|
+
e.preventDefault();
|
|
24144
|
+
handleSelect(search.trim().toLowerCase());
|
|
24145
|
+
} else if (e.key === "Escape") {
|
|
24146
|
+
setIsOpen(false);
|
|
24147
|
+
setSearch("");
|
|
24148
|
+
}
|
|
24149
|
+
}, [search, handleSelect]);
|
|
24150
|
+
const filteredLanguages = search.trim() ? COMMON_LANGUAGES.filter((lang) => lang.includes(search.trim().toLowerCase())) : COMMON_LANGUAGES;
|
|
24151
|
+
const showCustomOption = search.trim() && !COMMON_LANGUAGES.includes(search.trim().toLowerCase()) && search.trim().toLowerCase() !== currentLanguage;
|
|
24152
|
+
if (!currentLanguage) return null;
|
|
24153
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", ref: dropdownRef, children: [
|
|
24154
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
24155
|
+
"button",
|
|
24156
|
+
{
|
|
24157
|
+
onClick: () => !disabled && !isChanging && setIsOpen(!isOpen),
|
|
24158
|
+
disabled: disabled || isChanging,
|
|
24159
|
+
className: cn3(
|
|
24160
|
+
"text-zinc-500 agent-sdk-light:text-zinc-500 ml-1 text-xs transition-colors",
|
|
24161
|
+
"hover:text-zinc-300 agent-sdk-light:hover:text-zinc-700",
|
|
24162
|
+
(disabled || isChanging) && "opacity-50 cursor-not-allowed",
|
|
24163
|
+
!disabled && !isChanging && "cursor-pointer"
|
|
24164
|
+
),
|
|
24165
|
+
children: isChanging ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1", children: [
|
|
24166
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 10, className: "animate-spin" }),
|
|
24167
|
+
currentLanguage
|
|
24168
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
24169
|
+
"\u2022 ",
|
|
24170
|
+
currentLanguage
|
|
24171
|
+
] })
|
|
24172
|
+
}
|
|
24173
|
+
),
|
|
24174
|
+
isOpen && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute left-0 top-full mt-1 z-50 w-48 bg-zinc-900 agent-sdk-light:bg-white border border-zinc-700/50 agent-sdk-light:border-zinc-200 rounded-lg shadow-xl overflow-hidden", children: [
|
|
24175
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2 border-b border-zinc-800/50 agent-sdk-light:border-zinc-100", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
24176
|
+
"input",
|
|
24177
|
+
{
|
|
24178
|
+
ref: inputRef,
|
|
24179
|
+
type: "text",
|
|
24180
|
+
value: search,
|
|
24181
|
+
onChange: (e) => setSearch(e.target.value),
|
|
24182
|
+
onKeyDown: handleKeyDown,
|
|
24183
|
+
placeholder: "\u641C\u7D22\u8BED\u8A00...",
|
|
24184
|
+
className: "w-full px-2 py-1.5 text-xs bg-zinc-800 agent-sdk-light:bg-zinc-100 text-zinc-200 agent-sdk-light:text-zinc-800 rounded-md border border-zinc-700/50 agent-sdk-light:border-zinc-200 outline-none focus:border-zinc-500 agent-sdk-light:focus:border-zinc-400 placeholder-zinc-600 agent-sdk-light:placeholder-zinc-400"
|
|
24185
|
+
}
|
|
24186
|
+
) }),
|
|
24187
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-h-48 overflow-y-auto p-1", children: [
|
|
24188
|
+
showCustomOption && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
24189
|
+
"button",
|
|
24190
|
+
{
|
|
24191
|
+
onClick: () => handleSelect(search.trim().toLowerCase()),
|
|
24192
|
+
disabled: isChanging,
|
|
24193
|
+
className: cn3(
|
|
24194
|
+
"flex items-center justify-between px-2 py-1.5 text-xs rounded-md transition-all w-full text-left",
|
|
24195
|
+
"text-zinc-300 agent-sdk-light:text-zinc-700",
|
|
24196
|
+
"hover:bg-zinc-800/70 agent-sdk-light:hover:bg-zinc-100",
|
|
24197
|
+
isChanging && "opacity-50 cursor-not-allowed"
|
|
24198
|
+
),
|
|
24199
|
+
children: [
|
|
24200
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
24201
|
+
'"',
|
|
24202
|
+
search.trim().toLowerCase(),
|
|
24203
|
+
'"'
|
|
24204
|
+
] }),
|
|
24205
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-zinc-600 agent-sdk-light:text-zinc-400", children: "\u56DE\u8F66\u786E\u8BA4" })
|
|
24206
|
+
]
|
|
24207
|
+
}
|
|
24208
|
+
),
|
|
24209
|
+
filteredLanguages.map((lang) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
24210
|
+
"button",
|
|
24211
|
+
{
|
|
24212
|
+
onClick: () => handleSelect(lang),
|
|
24213
|
+
disabled: isChanging,
|
|
24214
|
+
className: cn3(
|
|
24215
|
+
"flex items-center justify-between px-2 py-1.5 text-xs rounded-md transition-all w-full text-left",
|
|
24216
|
+
lang === currentLanguage ? "text-zinc-100 agent-sdk-light:text-zinc-900 bg-zinc-800/50 agent-sdk-light:bg-zinc-100" : "text-zinc-300 agent-sdk-light:text-zinc-700 hover:bg-zinc-800/70 agent-sdk-light:hover:bg-zinc-100",
|
|
24217
|
+
isChanging && "opacity-50 cursor-not-allowed"
|
|
24218
|
+
),
|
|
24219
|
+
children: [
|
|
24220
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: lang }),
|
|
24221
|
+
lang === currentLanguage && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { size: 12, className: "text-green-400 agent-sdk-light:text-green-600 flex-shrink-0" })
|
|
24222
|
+
]
|
|
24223
|
+
},
|
|
24224
|
+
lang
|
|
24225
|
+
)),
|
|
24226
|
+
filteredLanguages.length === 0 && !showCustomOption && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2 py-3 text-xs text-zinc-600 agent-sdk-light:text-zinc-400 text-center", children: "\u65E0\u5339\u914D\u7ED3\u679C" })
|
|
24227
|
+
] })
|
|
24228
|
+
] })
|
|
24229
|
+
] });
|
|
24230
|
+
}
|
|
23866
24231
|
var ArtifactViewer = React16.memo(function ArtifactViewer2({
|
|
23867
24232
|
artifact,
|
|
23868
24233
|
isOpen,
|
|
@@ -23880,13 +24245,20 @@ var ArtifactViewer = React16.memo(function ArtifactViewer2({
|
|
|
23880
24245
|
onContentChange,
|
|
23881
24246
|
onSave,
|
|
23882
24247
|
onVisibilityChange,
|
|
23883
|
-
onDelete
|
|
24248
|
+
onDelete,
|
|
24249
|
+
onTypeChange,
|
|
24250
|
+
onLanguageChange,
|
|
24251
|
+
onTitleChange
|
|
23884
24252
|
}) {
|
|
23885
24253
|
const [viewMode, setViewMode] = React16.useState(defaultView);
|
|
23886
24254
|
const [isEditing, setIsEditing] = React16.useState(false);
|
|
23887
24255
|
const [editContent, setEditContent] = React16.useState("");
|
|
23888
24256
|
const [undoStack, setUndoStack] = React16.useState([]);
|
|
23889
24257
|
const [redoStack, setRedoStack] = React16.useState([]);
|
|
24258
|
+
const [isEditingTitle, setIsEditingTitle] = React16.useState(false);
|
|
24259
|
+
const [editingTitle, setEditingTitle] = React16.useState("");
|
|
24260
|
+
const [isSavingTitle, setIsSavingTitle] = React16.useState(false);
|
|
24261
|
+
const titleInputRef = React16.useRef(null);
|
|
23890
24262
|
React16.useEffect(() => {
|
|
23891
24263
|
if (artifact) {
|
|
23892
24264
|
if (artifact.type === "html" || artifact.type === "markdown" || artifact.type === "svg") {
|
|
@@ -23898,8 +24270,9 @@ var ArtifactViewer = React16.memo(function ArtifactViewer2({
|
|
|
23898
24270
|
setEditContent(artifact.content);
|
|
23899
24271
|
setUndoStack([]);
|
|
23900
24272
|
setRedoStack([]);
|
|
24273
|
+
setIsEditingTitle(false);
|
|
23901
24274
|
}
|
|
23902
|
-
}, [artifact?.id]);
|
|
24275
|
+
}, [artifact?.id, artifact?.type]);
|
|
23903
24276
|
React16.useEffect(() => {
|
|
23904
24277
|
if (artifact && !isEditing) {
|
|
23905
24278
|
setEditContent(artifact.content);
|
|
@@ -23912,6 +24285,7 @@ var ArtifactViewer = React16.memo(function ArtifactViewer2({
|
|
|
23912
24285
|
const handleStartEdit = () => {
|
|
23913
24286
|
setEditContent(artifact.content);
|
|
23914
24287
|
setUndoStack([artifact.content]);
|
|
24288
|
+
handleStartEditTitle();
|
|
23915
24289
|
setRedoStack([]);
|
|
23916
24290
|
setIsEditing(true);
|
|
23917
24291
|
setViewMode("code");
|
|
@@ -23946,6 +24320,43 @@ var ArtifactViewer = React16.memo(function ArtifactViewer2({
|
|
|
23946
24320
|
setEditContent(artifact.content);
|
|
23947
24321
|
setIsEditing(false);
|
|
23948
24322
|
};
|
|
24323
|
+
const handleStartEditTitle = React16.useCallback(() => {
|
|
24324
|
+
if (!onTitleChange || isEditing || isSavingTitle) return;
|
|
24325
|
+
setEditingTitle(artifact.title);
|
|
24326
|
+
setIsEditingTitle(true);
|
|
24327
|
+
}, [onTitleChange, isEditing, isSavingTitle, artifact.title]);
|
|
24328
|
+
const handleSaveTitle = React16.useCallback(async () => {
|
|
24329
|
+
const trimmed = editingTitle.trim();
|
|
24330
|
+
if (!trimmed || trimmed === artifact.title) {
|
|
24331
|
+
setIsEditingTitle(false);
|
|
24332
|
+
return;
|
|
24333
|
+
}
|
|
24334
|
+
setIsSavingTitle(true);
|
|
24335
|
+
try {
|
|
24336
|
+
await onTitleChange?.(artifact.id, trimmed);
|
|
24337
|
+
} finally {
|
|
24338
|
+
setIsSavingTitle(false);
|
|
24339
|
+
setIsEditingTitle(false);
|
|
24340
|
+
}
|
|
24341
|
+
}, [editingTitle, artifact.title, artifact.id, onTitleChange]);
|
|
24342
|
+
const handleCancelEditTitle = React16.useCallback(() => {
|
|
24343
|
+
setIsEditingTitle(false);
|
|
24344
|
+
}, []);
|
|
24345
|
+
const handleTitleKeyDown = React16.useCallback((e) => {
|
|
24346
|
+
if (e.key === "Enter") {
|
|
24347
|
+
e.preventDefault();
|
|
24348
|
+
handleSaveTitle();
|
|
24349
|
+
} else if (e.key === "Escape") {
|
|
24350
|
+
e.preventDefault();
|
|
24351
|
+
handleCancelEditTitle();
|
|
24352
|
+
}
|
|
24353
|
+
}, [handleSaveTitle, handleCancelEditTitle]);
|
|
24354
|
+
React16.useEffect(() => {
|
|
24355
|
+
if (isEditingTitle && titleInputRef.current) {
|
|
24356
|
+
titleInputRef.current.focus();
|
|
24357
|
+
titleInputRef.current.select();
|
|
24358
|
+
}
|
|
24359
|
+
}, [isEditingTitle]);
|
|
23949
24360
|
const displayContent = isEditing ? editContent : artifact.content;
|
|
23950
24361
|
const renderContent = () => {
|
|
23951
24362
|
if (isEditing) {
|
|
@@ -23986,7 +24397,7 @@ var ArtifactViewer = React16.memo(function ArtifactViewer2({
|
|
|
23986
24397
|
switch (artifact.type) {
|
|
23987
24398
|
case "html":
|
|
23988
24399
|
case "svg":
|
|
23989
|
-
return /* @__PURE__ */ jsxRuntime.jsx(HtmlPreview3, { content: displayContent });
|
|
24400
|
+
return /* @__PURE__ */ jsxRuntime.jsx(HtmlPreview3, { content: displayContent, config });
|
|
23990
24401
|
case "markdown":
|
|
23991
24402
|
return /* @__PURE__ */ jsxRuntime.jsx(MarkdownPreview, { content: displayContent, config });
|
|
23992
24403
|
default:
|
|
@@ -24003,15 +24414,56 @@ var ArtifactViewer = React16.memo(function ArtifactViewer2({
|
|
|
24003
24414
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "h-full flex flex-col bg-zinc-900 agent-sdk-light:bg-white relative", children: [
|
|
24004
24415
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-4 py-3 border-b border-zinc-800/50 agent-sdk-light:border-zinc-200 bg-zinc-900/95 agent-sdk-light:bg-zinc-50 backdrop-blur-sm flex-shrink-0", children: [
|
|
24005
24416
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 min-w-0", children: [
|
|
24006
|
-
|
|
24417
|
+
onTypeChange ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
24418
|
+
ArtifactTypeSelector,
|
|
24419
|
+
{
|
|
24420
|
+
currentType: artifact.type,
|
|
24421
|
+
currentLanguage: artifact.language,
|
|
24422
|
+
onTypeChange: (newType, language) => onTypeChange(artifact.id, newType, language),
|
|
24423
|
+
disabled: isEditing
|
|
24424
|
+
}
|
|
24425
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-7 h-7 rounded-lg ${typeConfig2.bgColor} flex items-center justify-center flex-shrink-0`, children: /* @__PURE__ */ jsxRuntime.jsx(typeConfig2.icon, { size: 14, className: typeConfig2.color }) }),
|
|
24007
24426
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
|
|
24008
|
-
/* @__PURE__ */ jsxRuntime.
|
|
24427
|
+
isEditingTitle ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
24428
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
24429
|
+
"input",
|
|
24430
|
+
{
|
|
24431
|
+
ref: titleInputRef,
|
|
24432
|
+
type: "text",
|
|
24433
|
+
value: editingTitle,
|
|
24434
|
+
onChange: (e) => setEditingTitle(e.target.value),
|
|
24435
|
+
onKeyDown: handleTitleKeyDown,
|
|
24436
|
+
onBlur: handleSaveTitle,
|
|
24437
|
+
disabled: isSavingTitle,
|
|
24438
|
+
className: "text-sm font-medium text-zinc-100 agent-sdk-light:text-zinc-900 bg-zinc-800 agent-sdk-light:bg-zinc-100 border border-zinc-600 agent-sdk-light:border-zinc-300 rounded px-1.5 py-0.5 outline-none focus:border-zinc-400 agent-sdk-light:focus:border-zinc-500 w-full min-w-0"
|
|
24439
|
+
}
|
|
24440
|
+
),
|
|
24441
|
+
isSavingTitle && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 12, className: "text-zinc-500 animate-spin flex-shrink-0" })
|
|
24442
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
24443
|
+
"h3",
|
|
24444
|
+
{
|
|
24445
|
+
className: cn3(
|
|
24446
|
+
"text-sm font-medium text-zinc-100 agent-sdk-light:text-zinc-900 truncate",
|
|
24447
|
+
onTitleChange && !isEditing && "cursor-pointer hover:text-zinc-300 agent-sdk-light:hover:text-zinc-600"
|
|
24448
|
+
),
|
|
24449
|
+
onDoubleClick: handleStartEditTitle,
|
|
24450
|
+
title: onTitleChange && !isEditing ? "\u53CC\u51FB\u7F16\u8F91\u6807\u9898" : void 0,
|
|
24451
|
+
children: artifact.title
|
|
24452
|
+
}
|
|
24453
|
+
),
|
|
24009
24454
|
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: `text-xs ${typeConfig2.color}`, children: [
|
|
24010
24455
|
typeConfig2.label,
|
|
24011
|
-
artifact.language && artifact.language !== artifact.type && /* @__PURE__ */ jsxRuntime.
|
|
24456
|
+
artifact.language && artifact.language !== artifact.type && (onLanguageChange ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
24457
|
+
ArtifactLanguageSelector,
|
|
24458
|
+
{
|
|
24459
|
+
currentLanguage: artifact.language,
|
|
24460
|
+
onLanguageChange: (lang) => onLanguageChange(artifact.id, lang),
|
|
24461
|
+
disabled: isEditing
|
|
24462
|
+
}
|
|
24463
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-zinc-500 agent-sdk-light:text-zinc-500 ml-1", children: [
|
|
24012
24464
|
"\u2022 ",
|
|
24013
24465
|
artifact.language
|
|
24014
|
-
] })
|
|
24466
|
+
] }))
|
|
24015
24467
|
] })
|
|
24016
24468
|
] })
|
|
24017
24469
|
] }),
|
|
@@ -24136,15 +24588,54 @@ var ArtifactViewer = React16.memo(function ArtifactViewer2({
|
|
|
24136
24588
|
isOpen,
|
|
24137
24589
|
onClose,
|
|
24138
24590
|
title: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
24139
|
-
|
|
24140
|
-
|
|
24591
|
+
onTypeChange ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
24592
|
+
ArtifactTypeSelector,
|
|
24593
|
+
{
|
|
24594
|
+
currentType: artifact.type,
|
|
24595
|
+
currentLanguage: artifact.language,
|
|
24596
|
+
onTypeChange: (newType, language) => onTypeChange(artifact.id, newType, language),
|
|
24597
|
+
disabled: isEditing
|
|
24598
|
+
}
|
|
24599
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-6 h-6 rounded-md ${typeConfig2.bgColor} flex items-center justify-center`, children: /* @__PURE__ */ jsxRuntime.jsx(typeConfig2.icon, { size: 14, className: typeConfig2.color }) }),
|
|
24600
|
+
isEditingTitle ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
24601
|
+
"input",
|
|
24602
|
+
{
|
|
24603
|
+
ref: titleInputRef,
|
|
24604
|
+
type: "text",
|
|
24605
|
+
value: editingTitle,
|
|
24606
|
+
onChange: (e) => setEditingTitle(e.target.value),
|
|
24607
|
+
onKeyDown: handleTitleKeyDown,
|
|
24608
|
+
onBlur: handleSaveTitle,
|
|
24609
|
+
disabled: isSavingTitle,
|
|
24610
|
+
className: "text-sm font-medium text-zinc-100 agent-sdk-light:text-zinc-900 bg-zinc-800 agent-sdk-light:bg-zinc-100 border border-zinc-600 agent-sdk-light:border-zinc-300 rounded px-1.5 py-0.5 outline-none focus:border-zinc-400 agent-sdk-light:focus:border-zinc-500 min-w-0 flex-1"
|
|
24611
|
+
}
|
|
24612
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
24613
|
+
"span",
|
|
24614
|
+
{
|
|
24615
|
+
className: cn3(
|
|
24616
|
+
"truncate",
|
|
24617
|
+
onTitleChange && !isEditing && "cursor-pointer hover:text-zinc-300 agent-sdk-light:hover:text-zinc-600"
|
|
24618
|
+
),
|
|
24619
|
+
onDoubleClick: handleStartEditTitle,
|
|
24620
|
+
title: onTitleChange && !isEditing ? "\u53CC\u51FB\u7F16\u8F91\u6807\u9898" : void 0,
|
|
24621
|
+
children: artifact.title
|
|
24622
|
+
}
|
|
24623
|
+
),
|
|
24624
|
+
isSavingTitle && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 12, className: "text-zinc-500 animate-spin flex-shrink-0" })
|
|
24141
24625
|
] }),
|
|
24142
24626
|
subtitle: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: typeConfig2.color, children: [
|
|
24143
24627
|
typeConfig2.label,
|
|
24144
|
-
artifact.language && artifact.language !== artifact.type && /* @__PURE__ */ jsxRuntime.
|
|
24628
|
+
artifact.language && artifact.language !== artifact.type && (onLanguageChange ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
24629
|
+
ArtifactLanguageSelector,
|
|
24630
|
+
{
|
|
24631
|
+
currentLanguage: artifact.language,
|
|
24632
|
+
onLanguageChange: (lang) => onLanguageChange(artifact.id, lang),
|
|
24633
|
+
disabled: isEditing
|
|
24634
|
+
}
|
|
24635
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-zinc-500 agent-sdk-light:text-zinc-500 ml-1", children: [
|
|
24145
24636
|
"\u2022 ",
|
|
24146
24637
|
artifact.language
|
|
24147
|
-
] })
|
|
24638
|
+
] }))
|
|
24148
24639
|
] }),
|
|
24149
24640
|
isFullscreen,
|
|
24150
24641
|
onFullscreenToggle,
|
|
@@ -25057,7 +25548,7 @@ function useArtifactPanel({ currentSessionId }) {
|
|
|
25057
25548
|
const existingArtifact = Object.values(artifacts).find(
|
|
25058
25549
|
(a) => {
|
|
25059
25550
|
const sameContent = a.currentContent === data.content && a.type === data.type;
|
|
25060
|
-
const sameId = a?.metadata?.workId === data.metadata?.workId;
|
|
25551
|
+
const sameId = !!data.metadata?.workId && a?.metadata?.workId === data.metadata?.workId;
|
|
25061
25552
|
return sameContent || sameId;
|
|
25062
25553
|
}
|
|
25063
25554
|
);
|
|
@@ -25119,7 +25610,8 @@ function useArtifactPanel({ currentSessionId }) {
|
|
|
25119
25610
|
setActiveArtifact,
|
|
25120
25611
|
removeArtifact,
|
|
25121
25612
|
reorderArtifacts,
|
|
25122
|
-
updateArtifactContent
|
|
25613
|
+
updateArtifactContent,
|
|
25614
|
+
upsertArtifact
|
|
25123
25615
|
};
|
|
25124
25616
|
}
|
|
25125
25617
|
|
|
@@ -25935,7 +26427,8 @@ var AgentChat = React16__namespace.default.forwardRef(({
|
|
|
25935
26427
|
setActiveArtifact,
|
|
25936
26428
|
removeArtifact,
|
|
25937
26429
|
reorderArtifacts,
|
|
25938
|
-
updateArtifactContent
|
|
26430
|
+
updateArtifactContent,
|
|
26431
|
+
upsertArtifact
|
|
25939
26432
|
} = useArtifactPanel({ currentSessionId: useAgentStore((state) => state.currentSession?.sessionId) });
|
|
25940
26433
|
const reconnectRef = React16.useRef(null);
|
|
25941
26434
|
const reconnectWrapper = React16.useCallback(async (messageId) => {
|
|
@@ -26409,6 +26902,52 @@ var AgentChat = React16__namespace.default.forwardRef(({
|
|
|
26409
26902
|
toast.error("\u5220\u9664\u4EA7\u7269\u5931\u8D25");
|
|
26410
26903
|
}
|
|
26411
26904
|
},
|
|
26905
|
+
onTypeChange: async (artifactId, newType, language) => {
|
|
26906
|
+
try {
|
|
26907
|
+
const content = activeArtifact?.currentContent || "";
|
|
26908
|
+
const res = await artifactService.updateContent(artifactId, content, {
|
|
26909
|
+
type: newType,
|
|
26910
|
+
language
|
|
26911
|
+
});
|
|
26912
|
+
if (res.success && res.data) {
|
|
26913
|
+
upsertArtifact(artifactService.normalizeEntry(res.data));
|
|
26914
|
+
toast.success("\u7C7B\u578B\u5DF2\u66F4\u65B0");
|
|
26915
|
+
} else {
|
|
26916
|
+
toast.error("\u7C7B\u578B\u66F4\u65B0\u5931\u8D25");
|
|
26917
|
+
}
|
|
26918
|
+
} catch (err) {
|
|
26919
|
+
console.error("[AgentChat] Change artifact type failed:", err);
|
|
26920
|
+
toast.error("\u7C7B\u578B\u66F4\u65B0\u5931\u8D25");
|
|
26921
|
+
}
|
|
26922
|
+
},
|
|
26923
|
+
onLanguageChange: async (artifactId, language) => {
|
|
26924
|
+
try {
|
|
26925
|
+
const content = activeArtifact?.currentContent || "";
|
|
26926
|
+
const res = await artifactService.updateContent(artifactId, content, { language });
|
|
26927
|
+
if (res.success && res.data) {
|
|
26928
|
+
upsertArtifact(artifactService.normalizeEntry(res.data));
|
|
26929
|
+
} else {
|
|
26930
|
+
toast.error("\u8BED\u8A00\u66F4\u65B0\u5931\u8D25");
|
|
26931
|
+
}
|
|
26932
|
+
} catch (err) {
|
|
26933
|
+
console.error("[AgentChat] Change artifact language failed:", err);
|
|
26934
|
+
toast.error("\u8BED\u8A00\u66F4\u65B0\u5931\u8D25");
|
|
26935
|
+
}
|
|
26936
|
+
},
|
|
26937
|
+
onTitleChange: async (artifactId, title) => {
|
|
26938
|
+
try {
|
|
26939
|
+
const content = activeArtifact?.currentContent || "";
|
|
26940
|
+
const res = await artifactService.updateContent(artifactId, content, { title });
|
|
26941
|
+
if (res.success && res.data) {
|
|
26942
|
+
upsertArtifact(artifactService.normalizeEntry(res.data));
|
|
26943
|
+
} else {
|
|
26944
|
+
toast.error("\u6807\u9898\u66F4\u65B0\u5931\u8D25");
|
|
26945
|
+
}
|
|
26946
|
+
} catch (err) {
|
|
26947
|
+
console.error("[AgentChat] Change artifact title failed:", err);
|
|
26948
|
+
toast.error("\u6807\u9898\u66F4\u65B0\u5931\u8D25");
|
|
26949
|
+
}
|
|
26950
|
+
},
|
|
26412
26951
|
onVisibilityChange: async (artifactId, isPublic) => {
|
|
26413
26952
|
try {
|
|
26414
26953
|
const res = await artifactService.updateVisibility(artifactId, isPublic);
|
|
@@ -26944,19 +27483,58 @@ function ShareReplayPage({ shareId, onNavigateBack }) {
|
|
|
26944
27483
|
] });
|
|
26945
27484
|
}
|
|
26946
27485
|
var typeConfig = {
|
|
26947
|
-
html: { icon: lucideReact.Globe, label: "HTML", color: "
|
|
26948
|
-
svg: { icon: lucideReact.Globe, label: "SVG", color: "
|
|
26949
|
-
markdown: { icon: lucideReact.FileText, label: "Markdown", color: "
|
|
26950
|
-
json: { icon: lucideReact.FileJson, label: "JSON", color: "
|
|
26951
|
-
code: { icon: lucideReact.FileCode, label: "Code", color: "
|
|
26952
|
-
text: { icon: lucideReact.FileText, label: "Text", color: "
|
|
26953
|
-
image: { icon: lucideReact.FileImage, label: "Image", color: "
|
|
26954
|
-
video: { icon: lucideReact.Video, label: "Video", color: "
|
|
27486
|
+
html: { icon: lucideReact.Globe, label: "HTML", color: "#fb923c" },
|
|
27487
|
+
svg: { icon: lucideReact.Globe, label: "SVG", color: "#fb923c" },
|
|
27488
|
+
markdown: { icon: lucideReact.FileText, label: "Markdown", color: "#60a5fa" },
|
|
27489
|
+
json: { icon: lucideReact.FileJson, label: "JSON", color: "#facc15" },
|
|
27490
|
+
code: { icon: lucideReact.FileCode, label: "Code", color: "#c084fc" },
|
|
27491
|
+
text: { icon: lucideReact.FileText, label: "Text", color: "#a1a1aa" },
|
|
27492
|
+
image: { icon: lucideReact.FileImage, label: "Image", color: "#4ade80" },
|
|
27493
|
+
video: { icon: lucideReact.Video, label: "Video", color: "#f472b6" }
|
|
26955
27494
|
};
|
|
27495
|
+
function FullscreenHtmlPreview({ content }) {
|
|
27496
|
+
const blobUrl = React16.useMemo(() => {
|
|
27497
|
+
const processed = resolveHtmlAssetUrls(content);
|
|
27498
|
+
const styleInjection = `
|
|
27499
|
+
<style>
|
|
27500
|
+
html, body { margin: 0; padding: 0; width: 100%; min-height: 100%; box-sizing: border-box; }
|
|
27501
|
+
* { box-sizing: border-box; }
|
|
27502
|
+
</style>`;
|
|
27503
|
+
let modified = processed;
|
|
27504
|
+
if (processed.includes("<head>")) {
|
|
27505
|
+
modified = processed.replace("<head>", "<head>" + styleInjection);
|
|
27506
|
+
} else if (processed.includes("<html>")) {
|
|
27507
|
+
modified = processed.replace("<html>", "<html><head>" + styleInjection + "</head>");
|
|
27508
|
+
} else if (/<!(DOCTYPE|doctype)/i.test(processed)) {
|
|
27509
|
+
modified = processed.replace(/(<!DOCTYPE[^>]*>|<!doctype[^>]*>)/i, "$1<html><head>" + styleInjection + "</head><body>") + "</body></html>";
|
|
27510
|
+
} else {
|
|
27511
|
+
modified = `<!DOCTYPE html><html><head>${styleInjection}</head><body>${processed}</body></html>`;
|
|
27512
|
+
}
|
|
27513
|
+
const blob = new Blob([modified], { type: "text/html" });
|
|
27514
|
+
return URL.createObjectURL(blob);
|
|
27515
|
+
}, [content]);
|
|
27516
|
+
React16.useEffect(() => {
|
|
27517
|
+
return () => URL.revokeObjectURL(blobUrl);
|
|
27518
|
+
}, [blobUrl]);
|
|
27519
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
27520
|
+
"iframe",
|
|
27521
|
+
{
|
|
27522
|
+
src: blobUrl,
|
|
27523
|
+
style: { display: "block", width: "100%", height: "100%", border: "none", background: "white" },
|
|
27524
|
+
sandbox: "allow-scripts allow-same-origin allow-popups allow-forms allow-modals",
|
|
27525
|
+
title: "HTML Preview"
|
|
27526
|
+
}
|
|
27527
|
+
);
|
|
27528
|
+
}
|
|
26956
27529
|
function PublicArtifactPage({ shareToken, onNavigateBack }) {
|
|
26957
27530
|
const [pageState, setPageState] = React16.useState("loading");
|
|
26958
27531
|
const [error, setError] = React16.useState(null);
|
|
26959
27532
|
const [artifact, setArtifact] = React16.useState(null);
|
|
27533
|
+
const [isTheaterMode, setIsTheaterMode] = React16.useState(false);
|
|
27534
|
+
const [isBrowserFullscreen, setIsBrowserFullscreen] = React16.useState(false);
|
|
27535
|
+
const [showTheaterControls, setShowTheaterControls] = React16.useState(true);
|
|
27536
|
+
const theaterTimerRef = React16.useRef(null);
|
|
27537
|
+
const isFullscreenSupported = typeof document !== "undefined" && typeof document.documentElement?.requestFullscreen === "function";
|
|
26960
27538
|
React16.useEffect(() => {
|
|
26961
27539
|
if (!shareToken) {
|
|
26962
27540
|
setPageState("not-found");
|
|
@@ -26980,31 +27558,13 @@ function PublicArtifactPage({ shareToken, onNavigateBack }) {
|
|
|
26980
27558
|
}
|
|
26981
27559
|
load();
|
|
26982
27560
|
}, [shareToken]);
|
|
26983
|
-
const handleShare = React16.useCallback(() => {
|
|
26984
|
-
const url = window.location.href;
|
|
26985
|
-
navigator.clipboard.writeText(url);
|
|
26986
|
-
toast.success("\u94FE\u63A5\u5DF2\u590D\u5236\u5230\u526A\u8D34\u677F");
|
|
26987
|
-
}, []);
|
|
26988
27561
|
const handleDownload = React16.useCallback(() => {
|
|
26989
27562
|
if (!artifact) return;
|
|
26990
|
-
const
|
|
26991
|
-
|
|
26992
|
-
|
|
26993
|
-
|
|
26994
|
-
|
|
26995
|
-
code: artifact.language || "txt",
|
|
26996
|
-
text: "txt"
|
|
26997
|
-
};
|
|
26998
|
-
const ext = extMap[artifact.type] || "txt";
|
|
26999
|
-
const mimeMap = {
|
|
27000
|
-
html: "text/html",
|
|
27001
|
-
svg: "image/svg+xml",
|
|
27002
|
-
markdown: "text/markdown",
|
|
27003
|
-
json: "application/json",
|
|
27004
|
-
code: "text/plain",
|
|
27005
|
-
text: "text/plain"
|
|
27006
|
-
};
|
|
27007
|
-
const mime = mimeMap[artifact.type] || "text/plain";
|
|
27563
|
+
const type = artifact.type?.toLowerCase() ?? "text";
|
|
27564
|
+
const extMap = { html: "html", svg: "svg", markdown: "md", json: "json", code: artifact.language || "txt", text: "txt" };
|
|
27565
|
+
const ext = extMap[type] || "txt";
|
|
27566
|
+
const mimeMap = { html: "text/html", svg: "image/svg+xml", markdown: "text/markdown", json: "application/json", code: "text/plain", text: "text/plain" };
|
|
27567
|
+
const mime = mimeMap[type] || "text/plain";
|
|
27008
27568
|
const blob = new Blob([artifact.content], { type: mime });
|
|
27009
27569
|
const url = URL.createObjectURL(blob);
|
|
27010
27570
|
const link2 = document.createElement("a");
|
|
@@ -27015,15 +27575,85 @@ function PublicArtifactPage({ shareToken, onNavigateBack }) {
|
|
|
27015
27575
|
document.body.removeChild(link2);
|
|
27016
27576
|
URL.revokeObjectURL(url);
|
|
27017
27577
|
}, [artifact]);
|
|
27578
|
+
const toggleTheaterMode = React16.useCallback(() => {
|
|
27579
|
+
setIsTheaterMode((prev) => !prev);
|
|
27580
|
+
setShowTheaterControls(true);
|
|
27581
|
+
}, []);
|
|
27582
|
+
const exitTheaterMode = React16.useCallback(() => {
|
|
27583
|
+
setIsTheaterMode(false);
|
|
27584
|
+
setShowTheaterControls(true);
|
|
27585
|
+
}, []);
|
|
27586
|
+
const toggleBrowserFullscreen = React16.useCallback(() => {
|
|
27587
|
+
if (!document.fullscreenElement) {
|
|
27588
|
+
document.documentElement.requestFullscreen().catch(() => {
|
|
27589
|
+
});
|
|
27590
|
+
} else {
|
|
27591
|
+
document.exitFullscreen().catch(() => {
|
|
27592
|
+
});
|
|
27593
|
+
}
|
|
27594
|
+
}, []);
|
|
27595
|
+
React16.useEffect(() => {
|
|
27596
|
+
const handleFullscreenChange = () => {
|
|
27597
|
+
const isFs = !!document.fullscreenElement;
|
|
27598
|
+
setIsBrowserFullscreen(isFs);
|
|
27599
|
+
if (isFs) {
|
|
27600
|
+
setIsTheaterMode(true);
|
|
27601
|
+
setShowTheaterControls(true);
|
|
27602
|
+
} else {
|
|
27603
|
+
setIsTheaterMode(false);
|
|
27604
|
+
}
|
|
27605
|
+
};
|
|
27606
|
+
document.addEventListener("fullscreenchange", handleFullscreenChange);
|
|
27607
|
+
return () => document.removeEventListener("fullscreenchange", handleFullscreenChange);
|
|
27608
|
+
}, []);
|
|
27609
|
+
React16.useEffect(() => {
|
|
27610
|
+
if (!isTheaterMode) return;
|
|
27611
|
+
const handleInteraction = () => {
|
|
27612
|
+
setShowTheaterControls(true);
|
|
27613
|
+
if (theaterTimerRef.current) clearTimeout(theaterTimerRef.current);
|
|
27614
|
+
theaterTimerRef.current = setTimeout(() => setShowTheaterControls(false), 3e3);
|
|
27615
|
+
};
|
|
27616
|
+
theaterTimerRef.current = setTimeout(() => setShowTheaterControls(false), 3e3);
|
|
27617
|
+
window.addEventListener("mousemove", handleInteraction);
|
|
27618
|
+
window.addEventListener("touchstart", handleInteraction);
|
|
27619
|
+
return () => {
|
|
27620
|
+
window.removeEventListener("mousemove", handleInteraction);
|
|
27621
|
+
window.removeEventListener("touchstart", handleInteraction);
|
|
27622
|
+
if (theaterTimerRef.current) clearTimeout(theaterTimerRef.current);
|
|
27623
|
+
};
|
|
27624
|
+
}, [isTheaterMode]);
|
|
27625
|
+
React16.useEffect(() => {
|
|
27626
|
+
const handleKeyDown = (e) => {
|
|
27627
|
+
const tag = e.target?.tagName;
|
|
27628
|
+
if (tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT") return;
|
|
27629
|
+
if (e.key === "Escape") {
|
|
27630
|
+
if (document.fullscreenElement) return;
|
|
27631
|
+
if (isTheaterMode) exitTheaterMode();
|
|
27632
|
+
return;
|
|
27633
|
+
}
|
|
27634
|
+
if ((e.key === "f" || e.key === "F") && !e.ctrlKey && !e.metaKey && !e.altKey) {
|
|
27635
|
+
e.preventDefault();
|
|
27636
|
+
if (isFullscreenSupported) toggleBrowserFullscreen();
|
|
27637
|
+
return;
|
|
27638
|
+
}
|
|
27639
|
+
if ((e.key === "t" || e.key === "T") && !e.ctrlKey && !e.metaKey && !e.altKey) {
|
|
27640
|
+
e.preventDefault();
|
|
27641
|
+
toggleTheaterMode();
|
|
27642
|
+
}
|
|
27643
|
+
};
|
|
27644
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
27645
|
+
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
27646
|
+
}, [isTheaterMode, isFullscreenSupported, exitTheaterMode, toggleBrowserFullscreen, toggleTheaterMode]);
|
|
27018
27647
|
const renderContent = () => {
|
|
27019
27648
|
if (!artifact) return null;
|
|
27020
27649
|
const content = artifact.content;
|
|
27021
|
-
|
|
27650
|
+
const type = artifact.type?.toLowerCase() ?? "text";
|
|
27651
|
+
switch (type) {
|
|
27022
27652
|
case "html":
|
|
27023
27653
|
case "svg":
|
|
27024
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
27654
|
+
return /* @__PURE__ */ jsxRuntime.jsx(FullscreenHtmlPreview, { content });
|
|
27025
27655
|
case "markdown":
|
|
27026
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6 max-w-4xl mx-auto", children: /* @__PURE__ */ jsxRuntime.jsx(MarkdownPreview, { content }) });
|
|
27656
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "agent-sdk-theme", style: { background: "transparent", height: "100%", overflow: "auto" }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6 max-w-4xl mx-auto", children: /* @__PURE__ */ jsxRuntime.jsx(MarkdownPreview, { content }) }) });
|
|
27027
27657
|
case "image":
|
|
27028
27658
|
return /* @__PURE__ */ jsxRuntime.jsx(ImageArtifactPreview, { content });
|
|
27029
27659
|
case "video":
|
|
@@ -27032,73 +27662,90 @@ function PublicArtifactPage({ shareToken, onNavigateBack }) {
|
|
|
27032
27662
|
case "code":
|
|
27033
27663
|
case "text":
|
|
27034
27664
|
default:
|
|
27035
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
27036
|
-
CodeBlock3,
|
|
27037
|
-
{
|
|
27038
|
-
code: content,
|
|
27039
|
-
language: artifact.language || artifact.type
|
|
27040
|
-
}
|
|
27041
|
-
);
|
|
27665
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "agent-sdk-theme", style: { background: "transparent", height: "100%", overflow: "auto" }, children: /* @__PURE__ */ jsxRuntime.jsx(CodeBlock3, { code: content, language: artifact.language || type }) });
|
|
27042
27666
|
}
|
|
27043
27667
|
};
|
|
27044
27668
|
if (pageState === "loading") {
|
|
27045
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", {
|
|
27669
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", height: "100vh", background: "#09090b" }, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { size: 32, style: { color: "#d8ff00" }, className: "animate-spin" }) });
|
|
27046
27670
|
}
|
|
27047
27671
|
if (pageState === "not-found") {
|
|
27048
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
27049
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { size: 48,
|
|
27050
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", {
|
|
27051
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", {
|
|
27672
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", height: "100vh", background: "#09090b", gap: 16 }, children: [
|
|
27673
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { size: 48, style: { color: "#52525b" } }),
|
|
27674
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { style: { color: "#a1a1aa", fontSize: 18, margin: 0 }, children: "\u4EA7\u7269\u4E0D\u5B58\u5728\u6216\u5DF2\u8BBE\u4E3A\u79C1\u6709" }),
|
|
27675
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { style: { color: "#52525b", fontSize: 14, margin: 0 }, children: "\u8BF7\u68C0\u67E5\u94FE\u63A5\u662F\u5426\u6B63\u786E\uFF0C\u6216\u8054\u7CFB\u4F5C\u8005\u91CD\u65B0\u5206\u4EAB" }),
|
|
27052
27676
|
onNavigateBack && /* @__PURE__ */ jsxRuntime.jsx(
|
|
27053
27677
|
"button",
|
|
27054
27678
|
{
|
|
27055
27679
|
onClick: onNavigateBack,
|
|
27056
|
-
|
|
27680
|
+
style: { marginTop: 16, padding: "8px 16px", fontSize: 14, background: "#27272a", color: "white", border: "none", borderRadius: 8, cursor: "pointer" },
|
|
27057
27681
|
children: "\u8FD4\u56DE"
|
|
27058
27682
|
}
|
|
27059
27683
|
)
|
|
27060
27684
|
] });
|
|
27061
27685
|
}
|
|
27062
27686
|
if (pageState === "error") {
|
|
27063
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
27064
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { size: 48,
|
|
27065
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", {
|
|
27687
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", height: "100vh", background: "#09090b", gap: 16 }, children: [
|
|
27688
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { size: 48, style: { color: "#f87171" } }),
|
|
27689
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { style: { color: "#f87171", fontSize: 18, margin: 0 }, children: error || "\u52A0\u8F7D\u5931\u8D25" }),
|
|
27066
27690
|
onNavigateBack && /* @__PURE__ */ jsxRuntime.jsx(
|
|
27067
27691
|
"button",
|
|
27068
27692
|
{
|
|
27069
27693
|
onClick: onNavigateBack,
|
|
27070
|
-
|
|
27694
|
+
style: { marginTop: 16, padding: "8px 16px", fontSize: 14, background: "#27272a", color: "white", border: "none", borderRadius: 8, cursor: "pointer" },
|
|
27071
27695
|
children: "\u8FD4\u56DE"
|
|
27072
27696
|
}
|
|
27073
27697
|
)
|
|
27074
27698
|
] });
|
|
27075
27699
|
}
|
|
27076
27700
|
if (!artifact) return null;
|
|
27077
|
-
const
|
|
27701
|
+
const normalizedType = artifact.type?.toLowerCase() ?? "text";
|
|
27702
|
+
const config = typeConfig[normalizedType] || typeConfig.text;
|
|
27078
27703
|
const TypeIcon = config.icon;
|
|
27079
|
-
const canDownload = ["html", "svg", "markdown", "json", "code", "text"].includes(
|
|
27080
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
27081
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
27082
|
-
|
|
27704
|
+
const canDownload = ["html", "svg", "markdown", "json", "code", "text"].includes(normalizedType);
|
|
27705
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", height: "100vh", background: "#09090b" }, children: [
|
|
27706
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
|
|
27707
|
+
display: "flex",
|
|
27708
|
+
alignItems: "center",
|
|
27709
|
+
justifyContent: "space-between",
|
|
27710
|
+
padding: isTheaterMode ? "0 16px" : "10px 16px",
|
|
27711
|
+
maxHeight: isTheaterMode ? 0 : 200,
|
|
27712
|
+
overflow: "hidden",
|
|
27713
|
+
opacity: isTheaterMode ? 0 : 1,
|
|
27714
|
+
borderBottom: isTheaterMode ? "none" : "1px solid rgba(39, 39, 42, 0.5)",
|
|
27715
|
+
background: "rgba(9, 9, 11, 0.8)",
|
|
27716
|
+
backdropFilter: "blur(8px)",
|
|
27717
|
+
flexShrink: 0,
|
|
27718
|
+
transition: "max-height 0.3s ease, opacity 0.3s ease, padding 0.3s ease"
|
|
27719
|
+
}, children: [
|
|
27720
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 12, minWidth: 0 }, children: [
|
|
27083
27721
|
onNavigateBack && /* @__PURE__ */ jsxRuntime.jsx(
|
|
27084
27722
|
"button",
|
|
27085
27723
|
{
|
|
27086
27724
|
onClick: onNavigateBack,
|
|
27087
|
-
|
|
27725
|
+
style: { padding: 6, color: "#a1a1aa", background: "none", border: "none", borderRadius: 8, cursor: "pointer", flexShrink: 0 },
|
|
27088
27726
|
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeft, { size: 18 })
|
|
27089
27727
|
}
|
|
27090
27728
|
),
|
|
27091
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
27092
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", {
|
|
27093
|
-
|
|
27094
|
-
|
|
27095
|
-
|
|
27096
|
-
|
|
27097
|
-
|
|
27729
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 10, minWidth: 0 }, children: [
|
|
27730
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: {
|
|
27731
|
+
width: 28,
|
|
27732
|
+
height: 28,
|
|
27733
|
+
borderRadius: 8,
|
|
27734
|
+
display: "flex",
|
|
27735
|
+
alignItems: "center",
|
|
27736
|
+
justifyContent: "center",
|
|
27737
|
+
flexShrink: 0,
|
|
27738
|
+
background: `color-mix(in srgb, ${config.color} 15%, transparent)`
|
|
27739
|
+
}, children: /* @__PURE__ */ jsxRuntime.jsx(TypeIcon, { size: 14, style: { color: config.color } }) }),
|
|
27740
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { minWidth: 0 }, children: [
|
|
27741
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { style: { fontSize: 14, fontWeight: 500, color: "white", margin: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: artifact.title }),
|
|
27742
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 10, fontSize: 11, color: "#71717a", marginTop: 2 }, children: [
|
|
27743
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: config.color }, children: config.label }),
|
|
27744
|
+
artifact.sharedAt && /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "flex", alignItems: "center", gap: 4 }, children: [
|
|
27098
27745
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Calendar, { size: 10 }),
|
|
27099
27746
|
new Date(artifact.sharedAt).toLocaleDateString()
|
|
27100
27747
|
] }),
|
|
27101
|
-
artifact.viewCount !== void 0 && artifact.viewCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", {
|
|
27748
|
+
artifact.viewCount !== void 0 && artifact.viewCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "flex", alignItems: "center", gap: 4 }, children: [
|
|
27102
27749
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Eye, { size: 10 }),
|
|
27103
27750
|
artifact.viewCount
|
|
27104
27751
|
] })
|
|
@@ -27106,29 +27753,120 @@ function PublicArtifactPage({ shareToken, onNavigateBack }) {
|
|
|
27106
27753
|
] })
|
|
27107
27754
|
] })
|
|
27108
27755
|
] }),
|
|
27109
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
27110
|
-
|
|
27756
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 4 }, children: [
|
|
27757
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
27111
27758
|
"button",
|
|
27112
27759
|
{
|
|
27113
|
-
onClick:
|
|
27114
|
-
|
|
27115
|
-
title: "\
|
|
27116
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.
|
|
27760
|
+
onClick: toggleTheaterMode,
|
|
27761
|
+
style: { padding: 8, color: "#a1a1aa", background: "none", border: "none", borderRadius: 8, cursor: "pointer" },
|
|
27762
|
+
title: "\u6C89\u6D78\u6A21\u5F0F (T)",
|
|
27763
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MonitorPlay, { size: 16 })
|
|
27117
27764
|
}
|
|
27118
27765
|
),
|
|
27119
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
27766
|
+
isFullscreenSupported && /* @__PURE__ */ jsxRuntime.jsx(
|
|
27120
27767
|
"button",
|
|
27121
27768
|
{
|
|
27122
|
-
onClick:
|
|
27123
|
-
|
|
27124
|
-
title: "\
|
|
27125
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.
|
|
27769
|
+
onClick: toggleBrowserFullscreen,
|
|
27770
|
+
style: { padding: 8, color: "#a1a1aa", background: "none", border: "none", borderRadius: 8, cursor: "pointer" },
|
|
27771
|
+
title: isBrowserFullscreen ? "\u9000\u51FA\u5168\u5C4F (F)" : "\u5168\u5C4F (F)",
|
|
27772
|
+
children: isBrowserFullscreen ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Minimize2, { size: 16 }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Maximize2, { size: 16 })
|
|
27773
|
+
}
|
|
27774
|
+
),
|
|
27775
|
+
canDownload && /* @__PURE__ */ jsxRuntime.jsx(
|
|
27776
|
+
"button",
|
|
27777
|
+
{
|
|
27778
|
+
onClick: handleDownload,
|
|
27779
|
+
style: { padding: 8, color: "#a1a1aa", background: "none", border: "none", borderRadius: 8, cursor: "pointer" },
|
|
27780
|
+
title: "\u4E0B\u8F7D",
|
|
27781
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Download, { size: 16 })
|
|
27126
27782
|
}
|
|
27127
27783
|
)
|
|
27128
27784
|
] })
|
|
27129
27785
|
] }),
|
|
27130
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", {
|
|
27131
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", {
|
|
27786
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { flex: 1, overflow: "hidden" }, children: renderContent() }),
|
|
27787
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: {
|
|
27788
|
+
display: "flex",
|
|
27789
|
+
alignItems: "center",
|
|
27790
|
+
justifyContent: "center",
|
|
27791
|
+
padding: isTheaterMode ? "0" : "8px 0",
|
|
27792
|
+
maxHeight: isTheaterMode ? 0 : 50,
|
|
27793
|
+
overflow: "hidden",
|
|
27794
|
+
opacity: isTheaterMode ? 0 : 1,
|
|
27795
|
+
borderTop: isTheaterMode ? "none" : "1px solid rgba(39, 39, 42, 0.3)",
|
|
27796
|
+
background: "rgba(9, 9, 11, 0.5)",
|
|
27797
|
+
flexShrink: 0,
|
|
27798
|
+
transition: "max-height 0.3s ease, opacity 0.3s ease, padding 0.3s ease"
|
|
27799
|
+
}, children: /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 10, color: "#52525b" }, children: "Powered by BISHAN Agent" }) }),
|
|
27800
|
+
isTheaterMode && /* @__PURE__ */ jsxRuntime.jsx(
|
|
27801
|
+
"div",
|
|
27802
|
+
{
|
|
27803
|
+
onMouseEnter: () => setShowTheaterControls(true),
|
|
27804
|
+
style: {
|
|
27805
|
+
position: "fixed",
|
|
27806
|
+
top: 0,
|
|
27807
|
+
left: 0,
|
|
27808
|
+
right: 0,
|
|
27809
|
+
height: 40,
|
|
27810
|
+
zIndex: 99
|
|
27811
|
+
}
|
|
27812
|
+
}
|
|
27813
|
+
),
|
|
27814
|
+
isTheaterMode && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
|
|
27815
|
+
position: "fixed",
|
|
27816
|
+
top: 16,
|
|
27817
|
+
right: 16,
|
|
27818
|
+
zIndex: 100,
|
|
27819
|
+
display: "flex",
|
|
27820
|
+
alignItems: "center",
|
|
27821
|
+
gap: 8,
|
|
27822
|
+
opacity: showTheaterControls ? 1 : 0,
|
|
27823
|
+
transform: showTheaterControls ? "translateY(0)" : "translateY(-8px)",
|
|
27824
|
+
transition: "opacity 0.3s ease, transform 0.3s ease",
|
|
27825
|
+
pointerEvents: showTheaterControls ? "auto" : "none"
|
|
27826
|
+
}, children: [
|
|
27827
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
27828
|
+
"button",
|
|
27829
|
+
{
|
|
27830
|
+
onClick: exitTheaterMode,
|
|
27831
|
+
style: {
|
|
27832
|
+
display: "flex",
|
|
27833
|
+
alignItems: "center",
|
|
27834
|
+
gap: 6,
|
|
27835
|
+
padding: "8px 12px",
|
|
27836
|
+
background: "rgba(39, 39, 42, 0.9)",
|
|
27837
|
+
backdropFilter: "blur(8px)",
|
|
27838
|
+
border: "1px solid rgba(63, 63, 70, 0.5)",
|
|
27839
|
+
borderRadius: 8,
|
|
27840
|
+
color: "#a1a1aa",
|
|
27841
|
+
fontSize: 12,
|
|
27842
|
+
cursor: "pointer",
|
|
27843
|
+
whiteSpace: "nowrap"
|
|
27844
|
+
},
|
|
27845
|
+
title: "\u9000\u51FA\u6C89\u6D78\u6A21\u5F0F (ESC)",
|
|
27846
|
+
children: [
|
|
27847
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 14 }),
|
|
27848
|
+
"\u9000\u51FA\u6C89\u6D78"
|
|
27849
|
+
]
|
|
27850
|
+
}
|
|
27851
|
+
),
|
|
27852
|
+
isFullscreenSupported && /* @__PURE__ */ jsxRuntime.jsx(
|
|
27853
|
+
"button",
|
|
27854
|
+
{
|
|
27855
|
+
onClick: toggleBrowserFullscreen,
|
|
27856
|
+
style: {
|
|
27857
|
+
padding: 8,
|
|
27858
|
+
background: "rgba(39, 39, 42, 0.9)",
|
|
27859
|
+
backdropFilter: "blur(8px)",
|
|
27860
|
+
border: "1px solid rgba(63, 63, 70, 0.5)",
|
|
27861
|
+
borderRadius: 8,
|
|
27862
|
+
color: "#a1a1aa",
|
|
27863
|
+
cursor: "pointer"
|
|
27864
|
+
},
|
|
27865
|
+
title: isBrowserFullscreen ? "\u9000\u51FA\u5168\u5C4F (F)" : "\u5168\u5C4F (F)",
|
|
27866
|
+
children: isBrowserFullscreen ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Minimize2, { size: 14 }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Maximize2, { size: 14 })
|
|
27867
|
+
}
|
|
27868
|
+
)
|
|
27869
|
+
] })
|
|
27132
27870
|
] });
|
|
27133
27871
|
}
|
|
27134
27872
|
var AgentSDKProvider = ({
|