feat(canvas): 画布节点 - 合并发送到 Agent 快捷入口 (#523)

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
ddCatandCursor committed 2026-09-17 09:30:13 +08:00
commit 50bd8875fb
10 files changed
+49 -8

No files matched your search

+14 -1
View File
@@ -77,6 +77,7 @@ import { writeCanvasNodePrompt } from "@/lib/canvas/canvas-node-prompt";
import {
applyCanvasConnectionPromptSync,
buildCanvasAgentMentionReferences,
canvasResourceMentionToken,
buildCanvasNodeMentionReferenceMap,
buildCanvasResourceReferences,
getContextResourceNodes,
@@ -292,6 +293,7 @@ function InfiniteCanvasPage() {
const [selectedConnectionId, setSelectedConnectionId] = useState<string | null>(null);
const [hoveredNodeId, setHoveredNodeId] = useState<string | null>(null);
const [contextMenu, setContextMenu] = useState<ContextMenuState | null>(null);
const [agentPrefillPrompt, setAgentPrefillPrompt] = useState("");
const [isMiniMapOpen, setIsMiniMapOpen] = useState(false);
const [canvasAppearance, setCanvasAppearance] = useState<CanvasAppearance>(() => canvasAppearanceForTheme(colorTheme));
const [backgroundMode, setBackgroundMode] = useState<CanvasBackgroundMode>(DEFAULT_CANVAS_BACKGROUND_MODE);
@@ -333,6 +335,15 @@ function InfiniteCanvasPage() {
const [cinematicAgentEntry, setCinematicAgentEntry] = useState(false);
const { assistantOpen, closeAgent, openAgent } = useCanvasAssistantVisibility();
const agentMentionReferences = useMemo(() => buildCanvasAgentMentionReferences(nodes), [nodes]);
const sendSelectionToAgent = useCallback((nodeId?: string) => {
const ids = nodeId ? [nodeId] : Array.from(selectedNodeIdsRef.current);
const references = ids.map((id) => agentMentionReferences.find((reference) => reference.nodeId === id)).filter((reference): reference is CanvasResourceReference => Boolean(reference));
if (!references.length) return;
setAgentPrefillPrompt(`${references.map(canvasResourceMentionToken).join(" ")} `);
openAgent();
setContextMenu(null);
}, [agentMentionReferences, openAgent]);
const { tasks: activeTasks } = useCanvasActiveTasks(projectId, projectLoaded);
const { focusMode, enterFocusMode, exitFocusMode, toggleFocusMode } = useFocusMode();
const [focusDockRevealed, setFocusDockRevealed] = useState(false);
@@ -2582,7 +2593,7 @@ function InfiniteCanvasPage() {
) : null}
</div>
<CanvasCloudAgentPanel canvasId={projectId} domainProjectId={currentProject?.projectId} nodeCount={nodes.length} references={agentMentionReferences} open={assistantOpen} onOpen={openAgent} onCollapse={closeAgent} onFocusNode={(nodeId) => {
<CanvasCloudAgentPanel canvasId={projectId} domainProjectId={currentProject?.projectId} nodeCount={nodes.length} references={agentMentionReferences} prefillPrompt={agentPrefillPrompt} open={assistantOpen} onOpen={openAgent} onCollapse={closeAgent} onFocusNode={(nodeId) => {
if (!nodesRef.current.some((node) => node.id === nodeId)) { message.info("该节点已删除或尚未同步到画布"); return; }
focusCanvasNode(nodeId);
}} />
@@ -2697,6 +2708,7 @@ function InfiniteCanvasPage() {
onCreateReferenceGroup={createReferenceGroup}
onBatchConnect={() => beginBatchConnectionMode(Array.from(selectedNodeIds))}
onMergeVideos={() => void mergeSelectedVideos()}
onSendSelectionToAgent={() => sendSelectionToAgent()}
/>
) : null}
@@ -2843,6 +2855,7 @@ function InfiniteCanvasPage() {
onSpreadSelection={spreadSelectedNodes}
onCopySelection={copySelectedNodes}
onDeleteSelection={() => deleteNodes(selectedNodeIds)}
onSendToAgent={() => sendSelectionToAgent(contextMenu?.type === "node" && selectedNodeIds.size <= 1 ? contextMenu.nodeId : undefined)}
/>
<CanvasUploadModal open={uploadModalOpen} onClose={closeUploadModal} onUpload={handleUploadFiles} />