@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 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({ artifactId, content })
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 = (jsx66, data) => {
16386
+ this.custom = (jsx68, data) => {
16264
16387
  const id = (data == null ? void 0 : data.id) || toastsCounter++;
16265
16388
  this.create({
16266
- jsx: jsx66(id),
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({ content }) {
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.useMemo(() => {
21783
- const styleInjection = `
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
- let modifiedContent = content;
21798
- if (content.includes("<head>")) {
21799
- modifiedContent = content.replace("<head>", "<head>" + styleInjection);
21800
- } else if (content.includes("<html>")) {
21801
- modifiedContent = content.replace("<html>", "<html><head>" + styleInjection + "</head>");
21802
- } else if (content.includes("<!DOCTYPE") || content.includes("<!doctype")) {
21803
- modifiedContent = content.replace(/(<!DOCTYPE[^>]*>|<!doctype[^>]*>)/i, "$1<html><head>" + styleInjection + "</head><body>") + "</body></html>";
21804
- } else {
21805
- modifiedContent = `<!DOCTYPE html><html><head>${styleInjection}</head><body>${content}</body></html>`;
21806
- }
21807
- const blob = new Blob([modifiedContent], { type: "text/html" });
21808
- return URL.createObjectURL(blob);
21809
- }, [content]);
21810
- React16.useEffect(() => {
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
- URL.revokeObjectURL(blobUrl);
21945
+ active = false;
21946
+ if (currentUrl) URL.revokeObjectURL(currentUrl);
21813
21947
  };
21814
- }, [blobUrl]);
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
- /* @__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 }) }),
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.jsx("h3", { className: "text-sm font-medium text-zinc-100 agent-sdk-light:text-zinc-900 truncate", children: artifact.title }),
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.jsxs("span", { className: "text-zinc-500 agent-sdk-light:text-zinc-500 ml-1", children: [
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
- /* @__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 }) }),
24140
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: artifact.title })
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.jsxs("span", { className: "text-zinc-500 agent-sdk-light:text-zinc-500 ml-1", children: [
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: "text-orange-400", bgColor: "bg-orange-500/10" },
26948
- svg: { icon: lucideReact.Globe, label: "SVG", color: "text-orange-400", bgColor: "bg-orange-500/10" },
26949
- markdown: { icon: lucideReact.FileText, label: "Markdown", color: "text-blue-400", bgColor: "bg-blue-500/10" },
26950
- json: { icon: lucideReact.FileJson, label: "JSON", color: "text-yellow-400", bgColor: "bg-yellow-500/10" },
26951
- code: { icon: lucideReact.FileCode, label: "Code", color: "text-purple-400", bgColor: "bg-purple-500/10" },
26952
- text: { icon: lucideReact.FileText, label: "Text", color: "text-zinc-400", bgColor: "bg-zinc-500/10" },
26953
- image: { icon: lucideReact.FileImage, label: "Image", color: "text-green-400", bgColor: "bg-green-500/10" },
26954
- video: { icon: lucideReact.Video, label: "Video", color: "text-pink-400", bgColor: "bg-pink-500/10" }
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 extMap = {
26991
- html: "html",
26992
- svg: "svg",
26993
- markdown: "md",
26994
- json: "json",
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
- switch (artifact.type) {
27650
+ const type = artifact.type?.toLowerCase() ?? "text";
27651
+ switch (type) {
27022
27652
  case "html":
27023
27653
  case "svg":
27024
- return /* @__PURE__ */ jsxRuntime.jsx(HtmlPreview3, { content });
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", { className: "flex items-center justify-center h-screen bg-zinc-950", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "w-8 h-8 animate-spin text-[#d8ff00]" }) });
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", { className: "flex flex-col items-center justify-center h-screen bg-zinc-950 gap-4", children: [
27049
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { size: 48, className: "text-zinc-600" }),
27050
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-zinc-400 text-lg", children: "\u4EA7\u7269\u4E0D\u5B58\u5728\u6216\u5DF2\u8BBE\u4E3A\u79C1\u6709" }),
27051
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-zinc-600 text-sm", children: "\u8BF7\u68C0\u67E5\u94FE\u63A5\u662F\u5426\u6B63\u786E\uFF0C\u6216\u8054\u7CFB\u4F5C\u8005\u91CD\u65B0\u5206\u4EAB" }),
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
- className: "mt-4 px-4 py-2 text-sm bg-zinc-800 text-white rounded-lg hover:bg-zinc-700 transition-colors",
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", { className: "flex flex-col items-center justify-center h-screen bg-zinc-950 gap-4", children: [
27064
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { size: 48, className: "text-red-400" }),
27065
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-red-400 text-lg", children: error || "\u52A0\u8F7D\u5931\u8D25" }),
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
- className: "mt-4 px-4 py-2 text-sm bg-zinc-800 text-white rounded-lg hover:bg-zinc-700 transition-colors",
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 config = typeConfig[artifact.type] || typeConfig.text;
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(artifact.type);
27080
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col h-screen bg-zinc-950", children: [
27081
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-4 py-2.5 border-b border-zinc-800/50 bg-zinc-950/80 backdrop-blur-sm flex-shrink-0", children: [
27082
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 min-w-0", children: [
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
- className: "p-1.5 text-zinc-400 hover:text-white hover:bg-zinc-800 rounded-lg transition-colors flex-shrink-0",
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", { className: "flex items-center gap-2.5 min-w-0", children: [
27092
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-7 h-7 rounded-lg ${config.bgColor} flex items-center justify-center flex-shrink-0`, children: /* @__PURE__ */ jsxRuntime.jsx(TypeIcon, { size: 14, className: config.color }) }),
27093
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
27094
- /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-sm font-medium text-white truncate", children: artifact.title }),
27095
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2.5 text-[11px] text-zinc-500 mt-0.5", children: [
27096
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: config.color, children: config.label }),
27097
- artifact.sharedAt && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1", children: [
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", { className: "flex items-center gap-1", children: [
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", { className: "flex items-center gap-1 flex-shrink-0", children: [
27110
- canDownload && /* @__PURE__ */ jsxRuntime.jsx(
27756
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 4 }, children: [
27757
+ /* @__PURE__ */ jsxRuntime.jsx(
27111
27758
  "button",
27112
27759
  {
27113
- onClick: handleDownload,
27114
- className: "p-2 text-zinc-400 hover:text-white hover:bg-zinc-800 rounded-lg transition-colors",
27115
- title: "\u4E0B\u8F7D",
27116
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Download, { size: 16 })
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: handleShare,
27123
- className: "p-2 text-zinc-400 hover:text-[#d8ff00] hover:bg-zinc-800 rounded-lg transition-colors",
27124
- title: "\u590D\u5236\u5206\u4EAB\u94FE\u63A5",
27125
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Share2, { size: 16 })
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", { className: "flex-1 overflow-hidden", children: renderContent() }),
27131
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center py-2 border-t border-zinc-800/30 bg-zinc-950/50", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-zinc-600", children: "Powered by BISHAN Agent" }) })
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 = ({