feat: runnersok

This commit is contained in:
2026-03-29 01:22:33 +01:00
parent 26b395272d
commit 9607ff3478
24 changed files with 1613 additions and 221 deletions

View File

@@ -68,6 +68,8 @@ import {
import type { AppNode, AppEdge } from '@/lib/graph/nodeTypes'
import { toast } from 'sonner'
import { RECOLLECTION_VERSION } from '@/app/recollections/state/recollectionGraphStorage'
import { useRunStream, createAndStreamRun } from '@/hooks/useRunStream'
import { useRunStore } from '@/lib/graph/runStore'
const SNAP_GRID: [number, number] = [15, 15]
const DUPLICATE_OFFSET = { x: 30, y: 30 }
@@ -257,6 +259,33 @@ export function CanvasPage({ recollectionId, focusNodeId }: CanvasPageProps) {
const connectionPath = useCanvasConnectionPathFromStore()
// --- Run execution ---
const { connectToRun } = useRunStream()
const runStatus = useRunStore((s) => s.status)
const resetRun = useRunStore((s) => s.reset)
const markDirty = useRunStore((s) => s.markDirty)
// Mark run state as dirty when graph structure or data changes
const prevNodesLenRef = useRef(nodes.length)
const prevEdgesLenRef = useRef(edges.length)
useEffect(() => {
// Skip the initial render
if (prevNodesLenRef.current === nodes.length && prevEdgesLenRef.current === edges.length) return
prevNodesLenRef.current = nodes.length
prevEdgesLenRef.current = edges.length
markDirty()
}, [nodes.length, edges.length, markDirty])
const handleRun = useCallback(() => {
if (!recollectionId) return
if (runStatus === 'running' || runStatus === 'pending') return
// Reset previous run state, save, then run
resetRun()
save()
createAndStreamRun(recollectionId, { nodes, edges }, connectToRun).catch((err) => {
toast.error(`Run failed: ${err.message}`)
})
}, [recollectionId, nodes, edges, connectToRun, save, runStatus, resetRun])
const nodesRef = useRef(nodes)
nodesRef.current = nodes
const graphRef = useRef<{ nodes: AppNode[]; edges: AppEdge[] }>({ nodes: [], edges: [] })
@@ -464,6 +493,7 @@ export function CanvasPage({ recollectionId, focusNodeId }: CanvasPageProps) {
canDuplicate: selectedNodes.length > 0,
canCopy: selectedNodes.length === 1,
onFitView: () => flowActionsRef.current?.fitView?.(),
onRun: recollectionId ? handleRun : undefined,
}
setFluxSlot(slot)
return () => setFluxSlot(null)
@@ -481,6 +511,7 @@ export function CanvasPage({ recollectionId, focusNodeId }: CanvasPageProps) {
handleCopy,
handlePaste,
selectedNodes.length,
handleRun,
])
const graphContextValue = useMemo(