From 11df9e6fdef90eec08df540efb01e5d72b388d5e Mon Sep 17 00:00:00 2001 From: dextmorgn Date: Thu, 12 Feb 2026 23:39:21 +0100 Subject: [PATCH] fix(app): chat context --- .../src/components/chat/chat-prompt.tsx | 2 +- flowsint-app/src/hooks/use-chat.ts | 3 - flowsint-app/src/stores/graph-store.ts | 104 ++++++++++-------- 3 files changed, 62 insertions(+), 47 deletions(-) diff --git a/flowsint-app/src/components/chat/chat-prompt.tsx b/flowsint-app/src/components/chat/chat-prompt.tsx index 286fa664..c289ab68 100644 --- a/flowsint-app/src/components/chat/chat-prompt.tsx +++ b/flowsint-app/src/components/chat/chat-prompt.tsx @@ -21,7 +21,7 @@ const formatContext = (context: ChatContextFormat[]): string[] => { export const ChatPanel = ({ onSend, isLoading }: ChatPanelProps) => { const [input, setInput] = useState('') - const selectedNodes = useGraphStore((s) => s.getSelectedNodesWithEdgesAsList)() + const selectedNodes = useGraphStore((s) => s.selectedNodesWithEdgesAsList) const clearSelectedNodes = useGraphStore((s) => s.clearSelectedNodes) const textareaRef = useRef(null) diff --git a/flowsint-app/src/hooks/use-chat.ts b/flowsint-app/src/hooks/use-chat.ts index 1cb52eeb..e57ed35e 100644 --- a/flowsint-app/src/hooks/use-chat.ts +++ b/flowsint-app/src/hooks/use-chat.ts @@ -4,15 +4,12 @@ import { useMutation, useQueryClient, useQuery } from '@tanstack/react-query' import { toast } from 'sonner' import { chatCRUDService } from '@/api/chat-service' import { createChatTransport } from '@/api/chat-transport' -import { useGraphStore } from '@/stores/graph-store' import { useChatState } from '@/stores/use-chat-store' import { useParams } from '@tanstack/react-router' import { queryKeys } from '@/api/query-keys' import { toUIMessage } from '@/types/chat' -import type { ChatContextFormat } from '@/types' export const useChat = () => { - const selectedNodes = useGraphStore((s) => s.selectedNodes) const currentChatId = useChatState((s) => s.currentChatId) const setCurrentChatId = useChatState((s) => s.setCurrentChatId) const deleteChat = useChatState((s) => s.deleteChat) diff --git a/flowsint-app/src/stores/graph-store.ts b/flowsint-app/src/stores/graph-store.ts index 2e425f0c..ad6eb463 100644 --- a/flowsint-app/src/stores/graph-store.ts +++ b/flowsint-app/src/stores/graph-store.ts @@ -76,7 +76,7 @@ interface GraphState { edgesLength: number getNodesLength: () => number getEdgesLength: () => number - getSelectedNodesWithEdgesAsList: () => ChatContextFormat[] + selectedNodesWithEdgesAsList: ChatContextFormat[] } // --- Helpers --- @@ -94,6 +94,41 @@ const computeFilteredEdges = (edges: GraphEdge[], filteredNodes: GraphNode[]): G return edges.filter((e) => nodeIds.has(e.source) && nodeIds.has(e.target)) } +const computeSelectedNodesWithEdgesAsList = ( + selectedNodes: GraphNode[], + edgesMapping: Map +): ChatContextFormat[] => { + const context: ChatContextFormat[] = [] + const remaining = new Map(selectedNodes.map((node) => [node.id, node])) + edgesMapping.forEach((edge) => { + const fromNode = remaining.get(edge.source) + const toNode = remaining.get(edge.target) + if (fromNode && toNode) { + context.push({ + type: 'relation', + fromLabel: fromNode.nodeLabel, + fromType: fromNode.nodeType, + fromColor: fromNode.nodeColor, + toLabel: toNode.nodeLabel, + toType: toNode.nodeType, + toColor: toNode.nodeColor, + label: edge.label + }) + remaining.delete(edge.source) + remaining.delete(edge.target) + } + }) + remaining.forEach((node) => + context.push({ + type: 'node', + nodeType: node.nodeType, + nodeLabel: node.nodeLabel, + nodeColor: node?.nodeColor + }) + ) + return context +} + // --- Store --- export const useGraphStore = create()( persist( @@ -121,7 +156,8 @@ export const useGraphStore = create()( const filteredNodes = computeFilteredNodes(nodes, filters) const filteredEdges = computeFilteredEdges(edges, filteredNodes) const edgesMapping = new Map(edges.map((edge) => [edge.id, edge])) - set({ edges, filteredNodes, filteredEdges, edgesMapping }) + const selectedNodesWithEdgesAsList = computeSelectedNodesWithEdgesAsList(get().selectedNodes, edgesMapping) + set({ edges, filteredNodes, filteredEdges, edgesMapping, selectedNodesWithEdgesAsList }) }, addNode: (newNode) => { @@ -154,7 +190,8 @@ export const useGraphStore = create()( edgesMapping.set(edgeWithId.id, edgeWithId) const filteredNodes = computeFilteredNodes(nodes, filters) const filteredEdges = computeFilteredEdges(edges, filteredNodes) - set({ edges, filteredNodes, filteredEdges, edgesMapping }) + const selectedNodesWithEdgesAsList = computeSelectedNodesWithEdgesAsList(get().selectedNodes, edgesMapping) + set({ edges, filteredNodes, filteredEdges, edgesMapping, selectedNodesWithEdgesAsList }) return edgeWithId }, @@ -179,7 +216,8 @@ export const useGraphStore = create()( const filteredNodes = computeFilteredNodes(nodes, filters) const filteredEdges = computeFilteredEdges(newEdges, filteredNodes) deleteKeys(edgesMapping, edgeIdsSet) - set({ edges: newEdges, filteredNodes, filteredEdges, edgesMapping }) + const selectedNodesWithEdgesAsList = computeSelectedNodesWithEdgesAsList(get().selectedNodes, edgesMapping) + set({ edges: newEdges, filteredNodes, filteredEdges, edgesMapping, selectedNodesWithEdgesAsList }) }, updateGraphData: (nodes, edges) => { @@ -188,7 +226,8 @@ export const useGraphStore = create()( const filteredEdges = computeFilteredEdges(edges, filteredNodes) const nodesMapping = new Map(nodes.map((node) => [node.id, node])) const edgesMapping = new Map(edges.map((edge) => [edge.id, edge])) - set({ nodes, edges, filteredNodes, filteredEdges, nodesMapping, edgesMapping }) + const selectedNodesWithEdgesAsList = computeSelectedNodesWithEdgesAsList(get().selectedNodes, edgesMapping) + set({ nodes, edges, filteredNodes, filteredEdges, nodesMapping, edgesMapping, selectedNodesWithEdgesAsList }) }, updateNode: (nodeId: string, updates: Partial) => { @@ -228,7 +267,8 @@ export const useGraphStore = create()( const filteredEdges = computeFilteredEdges(updatedEdges, filteredNodes) const edge = edgesMapping.get(edgeId) if (edge) edgesMapping.set(edgeId, { ...edge, ...updates } as GraphEdge) - set({ edges: updatedEdges, filteredNodes, filteredEdges, edgesMapping }) + const selectedNodesWithEdgesAsList = computeSelectedNodesWithEdgesAsList(get().selectedNodes, edgesMapping) + set({ edges: updatedEdges, filteredNodes, filteredEdges, edgesMapping, selectedNodesWithEdgesAsList }) }, replaceNode: (oldId, newId, nodeProperties) => { @@ -256,13 +296,15 @@ export const useGraphStore = create()( // Update edgesMapping const newEdgesMapping = new Map(updatedEdges.map((edge) => [edge.id, edge])) setCurrentNodeId(newId) + const selectedNodesWithEdgesAsList = computeSelectedNodesWithEdgesAsList(get().selectedNodes, newEdgesMapping) set({ nodes: updatedNodes, edges: updatedEdges, filteredNodes, filteredEdges, nodesMapping, - edgesMapping: newEdgesMapping + edgesMapping: newEdgesMapping, + selectedNodesWithEdgesAsList }) }, @@ -297,9 +339,12 @@ export const useGraphStore = create()( } return null }, - setSelectedNodes: (nodes) => set({ selectedNodes: nodes }), + setSelectedNodes: (nodes) => { + const selectedNodesWithEdgesAsList = computeSelectedNodesWithEdgesAsList(nodes, get().edgesMapping) + set({ selectedNodes: nodes, selectedNodesWithEdgesAsList }) + }, setSelectedEdges: (edges) => set({ selectedEdges: edges }), - clearSelectedNodes: () => set({ selectedNodes: [] }), + clearSelectedNodes: () => set({ selectedNodes: [], selectedNodesWithEdgesAsList: [] }), clearSelectedEdges: () => set({ selectedEdges: [] }), toggleNodeSelection: (node, multiSelect = false) => { const { selectedNodes, currentNodeId } = get() @@ -328,7 +373,10 @@ export const useGraphStore = create()( if (hasSelectionChanges || hasCurrentNodeChanges) { set({ selectedNodes: newSelected, - currentNodeId: newCurrentNodeId + currentNodeId: newCurrentNodeId, + ...(hasSelectionChanges && { + selectedNodesWithEdgesAsList: computeSelectedNodesWithEdgesAsList(newSelected, get().edgesMapping) + }) }) } }, @@ -436,41 +484,11 @@ export const useGraphStore = create()( openNodeEditorModal: false, currentNodeType: null, filteredNodes: get().nodes, - filteredEdges: get().edges + filteredEdges: get().edges, + selectedNodesWithEdgesAsList: [] }) }, - getSelectedNodesWithEdgesAsList: () => { - const { selectedNodes, edgesMapping } = get() - let context: ChatContextFormat[] = [] - const selectedNodesMapping = new Map(selectedNodes.map((node) => [node.id, node])) - edgesMapping.forEach((edge) => { - const fromNode = selectedNodesMapping.get(edge.source) - const toNode = selectedNodesMapping.get(edge.target) - if (fromNode && toNode) { - context.push({ - type: 'relation', - fromLabel: fromNode.nodeLabel, - fromType: fromNode.nodeType, - fromColor: fromNode.nodeColor, - toLabel: toNode.nodeLabel, - toType: toNode.nodeType, - toColor: toNode.nodeColor, - label: edge.label - }) - selectedNodesMapping.delete(edge.source) - selectedNodesMapping.delete(edge.target) - } - }) - selectedNodesMapping.forEach((node) => - context.push({ - type: 'node', - nodeType: node.nodeType, - nodeLabel: node.nodeLabel, - nodeColor: node?.nodeColor - }) - ) - return context - }, + selectedNodesWithEdgesAsList: [], // === Utils === nodesLength: 0,