feat: add ArtifactSlice and integrate artifact preview into skill editor tabs

Introduce a dedicated Zustand ArtifactSlice to manage artifact selection
state with mutual exclusion against the main file tree. Artifact files
from the sandbox can now be opened as tabs in the skill editor, rendered
via a lightweight ArtifactContentPanel that reuses ReadOnlyFilePreview.
This commit is contained in:
yyh
2026-01-29 17:52:41 +08:00
parent 9d99675a1d
commit 92731bffba
10 changed files with 148 additions and 8 deletions

View File

@ -6,6 +6,7 @@ import * as React from 'react'
import { useCallback, useState } from 'react'
import { useTranslation } from 'react-i18next'
import FolderSpark from '@/app/components/base/icons/src/vender/workflow/FolderSpark'
import { useStore, useWorkflowStore } from '@/app/components/workflow/store'
import { useAppContext } from '@/context/app-context'
import { useDownloadSandboxFile, useSandboxFilesTree } from '@/service/use-sandbox-file'
import { cn } from '@/utils/classnames'
@ -26,11 +27,17 @@ const ArtifactsSection = ({ className }: ArtifactsSectionProps) => {
const { data: treeData, hasFiles, isLoading } = useSandboxFilesTree(sandboxId)
const downloadMutation = useDownloadSandboxFile(sandboxId)
const storeApi = useWorkflowStore()
const selectedArtifactPath = useStore(s => s.selectedArtifactPath)
const handleToggle = useCallback(() => {
setIsExpanded(prev => !prev)
}, [])
const handleSelect = useCallback((node: SandboxFileTreeNode) => {
storeApi.getState().selectArtifact(node.path)
}, [storeApi])
const handleDownload = useCallback(async (node: SandboxFileTreeNode) => {
try {
const ticket = await downloadMutation.mutateAsync(node.path)
@ -91,6 +98,8 @@ const ArtifactsSection = ({ className }: ArtifactsSectionProps) => {
<ArtifactsTree
data={treeData}
onDownload={handleDownload}
onSelect={handleSelect}
selectedPath={selectedArtifactPath ?? undefined}
isDownloading={downloadMutation.isPending}
/>
)