diff --git a/api/core/app/apps/advanced_chat/generate_task_pipeline.py b/api/core/app/apps/advanced_chat/generate_task_pipeline.py index c4d89b8b2f..b695dd0bef 100644 --- a/api/core/app/apps/advanced_chat/generate_task_pipeline.py +++ b/api/core/app/apps/advanced_chat/generate_task_pipeline.py @@ -549,7 +549,6 @@ class AdvancedChatAppGenerateTaskPipeline(GraphRuntimeStateSupport): result=delta_text, tool_elapsed_time=tool_elapsed_time, ) - self._task_state.answer += delta_text case _: pass yield self._message_cycle_manager.message_to_stream_response( diff --git a/web/app/components/workflow/shortcuts-name.tsx b/web/app/components/workflow/shortcuts-name.tsx index d0ce007f61..a31528d00c 100644 --- a/web/app/components/workflow/shortcuts-name.tsx +++ b/web/app/components/workflow/shortcuts-name.tsx @@ -3,7 +3,7 @@ import { cn } from '@/utils/classnames' import { getKeyboardKeyNameBySystem } from './utils' type ShortcutsNameProps = { - keys: string[] + keys: readonly string[] className?: string textColor?: 'default' | 'secondary' } diff --git a/web/app/components/workflow/skill/file-tree/index.tsx b/web/app/components/workflow/skill/file-tree/index.tsx index 5e41e7802b..7a3e811cbb 100644 --- a/web/app/components/workflow/skill/file-tree/index.tsx +++ b/web/app/components/workflow/skill/file-tree/index.tsx @@ -17,8 +17,10 @@ import { useStore, useWorkflowStore } from '@/app/components/workflow/store' import { cn } from '@/utils/classnames' import { CONTEXT_MENU_TYPE, ROOT_ID } from '../constants' import { useInlineCreateNode } from '../hooks/use-inline-create-node' +import { usePasteOperation } from '../hooks/use-paste-operation' import { useRootFileDrop } from '../hooks/use-root-file-drop' import { useSkillAssetTreeData } from '../hooks/use-skill-asset-tree' +import { useSkillShortcuts } from '../hooks/use-skill-shortcuts' import { useSyncTreeWithActiveTab } from '../hooks/use-sync-tree-with-active-tab' import ArtifactsSection from './artifacts-section' import DragActionTooltip from './drag-action-tooltip' @@ -62,7 +64,6 @@ const FileTree: React.FC = ({ className }) => { const expandedFolderIds = useStore(s => s.expandedFolderIds) const activeTabId = useStore(s => s.activeTabId) - const selectedTreeNodeId = useStore(s => s.selectedTreeNodeId) const dragOverFolderId = useStore(s => s.dragOverFolderId) const searchTerm = useStore(s => s.fileTreeSearchTerm) const storeApi = useWorkflowStore() @@ -123,30 +124,37 @@ const FileTree: React.FC = ({ className }) => { }, [storeApi]) const handleSelect = useCallback((nodes: NodeApi[]) => { - const selectedId = nodes[0]?.id ?? null - storeApi.getState().setSelectedTreeNodeId(selectedId) + storeApi.getState().setSelectedNodeIds(nodes.map(n => n.id)) }, [storeApi]) - // Clicking blank area clears selection for root-level creation const handleBlankAreaClick = useCallback(() => { - storeApi.getState().setSelectedTreeNodeId(null) - }, [storeApi]) + treeRef.current?.deselectAll() + storeApi.getState().clearSelection() + }, [storeApi, treeRef]) const handleBlankAreaContextMenu = useCallback((e: React.MouseEvent) => { e.preventDefault() - storeApi.getState().setSelectedTreeNodeId(null) + treeRef.current?.deselectAll() + storeApi.getState().clearSelection() storeApi.getState().setContextMenu({ top: e.clientY, left: e.clientX, type: CONTEXT_MENU_TYPE.BLANK, }) - }, [storeApi]) + }, [storeApi, treeRef]) useSyncTreeWithActiveTab({ treeRef, activeTabId, }) + useSkillShortcuts({ treeRef }) + + usePasteOperation({ + treeRef, + treeData: treeData ?? undefined, + }) + if (isLoading) { return (
@@ -208,6 +216,7 @@ const FileTree: React.FC = ({ className }) => { return ( <>
= ({ className }) => { indent={20} overscanCount={5} openByDefault={false} - selection={selectedTreeNodeId ?? undefined} initialOpenState={initialOpensObject} onToggle={handleToggle} onSelect={handleSelect} diff --git a/web/app/components/workflow/skill/file-tree/menu-item.tsx b/web/app/components/workflow/skill/file-tree/menu-item.tsx index 3af2799292..1fc6356e50 100644 --- a/web/app/components/workflow/skill/file-tree/menu-item.tsx +++ b/web/app/components/workflow/skill/file-tree/menu-item.tsx @@ -4,6 +4,7 @@ import type { VariantProps } from 'class-variance-authority' import type { FC } from 'react' import { cva } from 'class-variance-authority' import * as React from 'react' +import ShortcutsName from '@/app/components/workflow/shortcuts-name' import { cn } from '@/utils/classnames' const menuItemVariants = cva( @@ -52,11 +53,12 @@ const labelVariants = cva('system-sm-regular text-text-secondary', { export type MenuItemProps = { icon: React.ElementType label: string + kbd?: readonly string[] onClick: React.MouseEventHandler disabled?: boolean } & VariantProps -const MenuItem: FC = ({ icon: Icon, label, onClick, disabled, variant }) => { +const MenuItem: FC = ({ icon: Icon, label, kbd, onClick, disabled, variant }) => { const handleClick = React.useCallback((event: React.MouseEvent) => { event.stopPropagation() onClick(event) @@ -70,7 +72,8 @@ const MenuItem: FC = ({ icon: Icon, label, onClick, disabled, var className={cn(menuItemVariants({ variant }))} >