diff --git a/frontend/src/app/workspace/chats/[thread_id]/page.tsx b/frontend/src/app/workspace/chats/[thread_id]/page.tsx index 5ae61615..4f1dcf52 100644 --- a/frontend/src/app/workspace/chats/[thread_id]/page.tsx +++ b/frontend/src/app/workspace/chats/[thread_id]/page.tsx @@ -14,7 +14,6 @@ import { DevDialogTitle, } from "@/components/ui/dev-dialog"; import { useSidebar } from "@/components/ui/sidebar"; -import { Skeleton } from "@/components/ui/skeleton"; import { ArtifactFileDetail, ArtifactFileList, @@ -27,7 +26,6 @@ import { InputBox } from "@/components/workspace/input-box"; import { MessageList } from "@/components/workspace/messages"; import { ThreadContext } from "@/components/workspace/messages/context"; import { ThreadTitle } from "@/components/workspace/thread-title"; -import { TokenUsageIndicator } from "@/components/workspace/token-usage-indicator"; import { Tooltip } from "@/components/workspace/tooltip"; import { useSpecificChatMode } from "@/components/workspace/use-chat-mode"; import { Welcome } from "@/components/workspace/welcome"; @@ -260,7 +258,6 @@ export default function ChatPage() { )}
- {/* */} ); } - -function InputBoxSkeleton() { - return ( -
-
- - -
-
- - -
- -
-
-
- ); -} diff --git a/frontend/src/components/workspace/artifacts/artifact-file-detail.tsx b/frontend/src/components/workspace/artifacts/artifact-file-detail.tsx index dcee6279..28710582 100644 --- a/frontend/src/components/workspace/artifacts/artifact-file-detail.tsx +++ b/frontend/src/components/workspace/artifacts/artifact-file-detail.tsx @@ -34,7 +34,6 @@ import { CodeEditor } from "@/components/workspace/code-editor"; import { useArtifactContent } from "@/core/artifacts/hooks"; import { urlOfArtifact } from "@/core/artifacts/utils"; import { useI18n } from "@/core/i18n/hooks"; -import { installSkill } from "@/core/skills/api"; import { streamdownPlugins } from "@/core/streamdown"; import { checkCodeFile, getFileName } from "@/core/utils/files"; import { useMarkdownDownload } from "@/core/utils/markdown-download"; @@ -61,7 +60,7 @@ export function ArtifactFileDetail({ }: { className?: string; filepath: string; - threadId: string; + threadId?: string; }) { const { t } = useI18n(); const { artifacts, setOpen, select, fullscreen, setFullscreen } = @@ -98,12 +97,18 @@ export function ArtifactFileDetail({ return (language === "html" && !isWriteFile) || language === "markdown"; }, [isWriteFile, language]); const artifactUrl = useMemo(() => { + if (!threadId) { + return ""; + } return urlOfArtifact({ filepath, threadId }); }, [filepath, threadId]); const artifactPreviewKind = useMemo(() => { return getArtifactPreviewKind(filepath); }, [filepath]); const artifactViewerSrcDoc = useMemo(() => { + if (!artifactUrl) { + return ""; + } return buildArtifactViewerSrcDoc({ artifactUrl, fileName, @@ -113,7 +118,7 @@ export function ArtifactFileDetail({ const { content } = useArtifactContent({ threadId, filepath: filepathFromProps, - enabled: isCodeFile && !isWriteFile, + enabled: Boolean(threadId) && isCodeFile && !isWriteFile, }); const displayContent = content ?? ""; @@ -126,7 +131,6 @@ export function ArtifactFileDetail({ }, [artifacts]); const [viewMode, setViewMode] = useState<"code" | "preview">("code"); - const [isInstalling, setIsInstalling] = useState(false); const [zoom, setZoom] = useState(80); // 是否可以转换为docx/pdf(仅markdown文件支持) @@ -172,28 +176,6 @@ export function ArtifactFileDetail({ } }, [previewable]); - const handleInstallSkill = useCallback(async () => { - if (isInstalling) return; - - setIsInstalling(true); - try { - const result = await installSkill({ - thread_id: threadId, - path: filepath, - }); - if (result.success) { - toast.success(result.message); - } else { - toast.error(result.message ?? "Failed to install skill"); - } - } catch (error) { - console.error("Failed to install skill:", error); - toast.error("Failed to install skill"); - } finally { - setIsInstalling(false); - } - }, [threadId, filepath, isInstalling]); - return ( // 给滚动遮挡头部定位relative handleInstallSkill(e, file)} > {installingFile === file ? ( @@ -109,20 +110,27 @@ export function ArtifactFileList({ {t.common.install} )} - e.stopPropagation()} - > - + + ) : ( + - + )} diff --git a/frontend/src/components/workspace/export-trigger.tsx b/frontend/src/components/workspace/export-trigger.tsx index b75d4e45..4d0d807d 100644 --- a/frontend/src/components/workspace/export-trigger.tsx +++ b/frontend/src/components/workspace/export-trigger.tsx @@ -21,7 +21,7 @@ import type { AgentThread } from "@/core/threads/types"; import { useThread } from "./messages/context"; import { Tooltip } from "./tooltip"; -export function ExportTrigger({ threadId }: { threadId: string }) { +export function ExportTrigger({ threadId }: { threadId?: string }) { const { t } = useI18n(); const { thread } = useThread(); @@ -49,7 +49,7 @@ export function ExportTrigger({ threadId }: { threadId: string }) { [messages, thread.values, threadId, t], ); - if (messages.length === 0) { + if (!threadId || messages.length === 0) { return null; } diff --git a/frontend/src/components/workspace/messages/message-list.tsx b/frontend/src/components/workspace/messages/message-list.tsx index c83194e2..69c08277 100644 --- a/frontend/src/components/workspace/messages/message-list.tsx +++ b/frontend/src/components/workspace/messages/message-list.tsx @@ -39,7 +39,7 @@ export function MessageList({ paddingBottom = 160, }: { className?: string; - threadId: string; + threadId?: string; thread: UseStream; /** When set (e.g. from onFinish), use instead of thread.messages so SSE end shows complete state. */ messagesOverride?: Message[]; @@ -98,7 +98,9 @@ export function MessageList({ className="mb-4" /> )} - + {threadId ? ( + + ) : null}
); } else if (group.type === "assistant:subagent") { diff --git a/frontend/src/components/workspace/thread-title.tsx b/frontend/src/components/workspace/thread-title.tsx index 642e4e6f..35e9b57e 100644 --- a/frontend/src/components/workspace/thread-title.tsx +++ b/frontend/src/components/workspace/thread-title.tsx @@ -40,6 +40,7 @@ export function ThreadTitle({ t.pages.newChat, t.pages.untitled, t.pages.appName, + thread, thread?.isThreadLoading, thread?.values, ]); diff --git a/frontend/src/core/artifacts/hooks.ts b/frontend/src/core/artifacts/hooks.ts index 4df9db70..6d875aba 100644 --- a/frontend/src/core/artifacts/hooks.ts +++ b/frontend/src/core/artifacts/hooks.ts @@ -11,7 +11,7 @@ export function useArtifactContent({ enabled, }: { filepath: string; - threadId: string; + threadId?: string; enabled?: boolean; }) { const isWriteFile = useMemo(() => { @@ -25,12 +25,17 @@ export function useArtifactContent({ return null; }, [filepath, isWriteFile, thread]); + const canFetch = Boolean(threadId) && enabled !== false; const { data, isLoading, error } = useQuery({ queryKey: ["artifact", filepath, threadId, isMock], queryFn: () => { - return loadArtifactContent({ filepath, threadId, isMock }); + return loadArtifactContent({ + filepath, + threadId: threadId ?? "", + isMock, + }); }, - enabled, + enabled: canFetch, // Cache artifact content for 5 minutes to avoid repeated fetches (especially for .skill ZIP extraction) staleTime: 5 * 60 * 1000, }); diff --git a/frontend/src/core/i18n/locales/en-US.ts b/frontend/src/core/i18n/locales/en-US.ts index a03cc86f..12f68950 100644 --- a/frontend/src/core/i18n/locales/en-US.ts +++ b/frontend/src/core/i18n/locales/en-US.ts @@ -1,6 +1,5 @@ import { CompassIcon, - GraduationCapIcon, ImageIcon, MicroscopeIcon, PenLineIcon, diff --git a/frontend/src/core/threads/hooks.ts b/frontend/src/core/threads/hooks.ts index c05310b8..eacd668a 100644 --- a/frontend/src/core/threads/hooks.ts +++ b/frontend/src/core/threads/hooks.ts @@ -456,7 +456,7 @@ export function useThreadStream({ : context.mode === "thinking" ? "low" : undefined), - thread_id: resolvedThreadId, + ...(resolvedThreadId ? { thread_id: resolvedThreadId } : {}), }, }, ); @@ -580,7 +580,7 @@ export function useSubmitThread({ }, context: { ...threadContext, - thread_id: threadId, + ...(threadId ? { thread_id: threadId } : {}), }, }, ); diff --git a/frontend/src/core/utils/markdown-download/converter.ts b/frontend/src/core/utils/markdown-download/converter.ts index cd503ed4..df81bbb2 100644 --- a/frontend/src/core/utils/markdown-download/converter.ts +++ b/frontend/src/core/utils/markdown-download/converter.ts @@ -156,7 +156,6 @@ export async function downloadMarkdownAsPdf( // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type async function loadHtml2Pdf(): Promise { const html2pdf = await import("html2pdf.js"); - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access return html2pdf.default; } diff --git a/frontend/src/hooks/use-selected-skill-listener.ts b/frontend/src/hooks/use-selected-skill-listener.ts index fc20d66d..313a6cfd 100644 --- a/frontend/src/hooks/use-selected-skill-listener.ts +++ b/frontend/src/hooks/use-selected-skill-listener.ts @@ -25,7 +25,7 @@ interface SkillError { interface UseSelectedSkillListenerOptions { /** 当前会话 thread_id,用于调用 bootstrapRemoteSkill */ - threadId: string | null; + threadId?: string | null; } interface UseSelectedSkillListenerReturn {