import type { PropertyBag } from '../model/Properties'; /** * Port data types. `exec` carries control flow (Blueprint-style white arrows); the others * carry values. `any` accepts every value type (variables, logging). */ export type PortType = 'exec' | 'number' | 'boolean' | 'string' | 'object' | 'any'; export interface PortRef { node: string; port: string; } /** * One node of a behavior graph. `type` names a NodeDef in the registry; `params` holds * the node's own settings (e.g. which key) and inline values of unconnected data inputs, * both keyed by the param / port key. */ export interface GraphNode { id: string; type: string; x: number; y: number; params: PropertyBag; } /** A connection from an output port to an input port. */ export interface GraphEdge { id: string; from: PortRef; to: PortRef; } export interface Graph { nodes: GraphNode[]; edges: GraphEdge[]; } export function createEmptyGraph(): Graph { return { nodes: [], edges: [] }; } export function findNode(graph: Graph, nodeId: string): GraphNode | undefined { return graph.nodes.find((n) => n.id === nodeId); } /** Edges arriving at one input port (data inputs allow at most one, exec inputs any number). */ export function edgesInto(graph: Graph, nodeId: string, port: string): GraphEdge[] { return graph.edges.filter((e) => e.to.node === nodeId && e.to.port === port); } /** Edges leaving one output port. */ export function edgesOutOf(graph: Graph, nodeId: string, port: string): GraphEdge[] { return graph.edges.filter((e) => e.from.node === nodeId && e.from.port === port); } /** Every edge touching a node (used when removing it). */ export function edgesOfNode(graph: Graph, nodeId: string): GraphEdge[] { return graph.edges.filter((e) => e.from.node === nodeId || e.to.node === nodeId); } /** Whether a value may flow from an output of type `from` into an input of type `to`. */ export function portsCompatible(from: PortType, to: PortType): boolean { if (from === 'exec' || to === 'exec') return from === to; return from === to || from === 'any' || to === 'any'; }