@particle-academy/fancy-flow 0.17.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-532A5QA3.js → chunk-FSC64BPD.js} +37 -3
- package/dist/chunk-FSC64BPD.js.map +1 -0
- package/dist/{chunk-MFMRTRPO.js → chunk-PHX4SBOD.js} +114 -5
- package/dist/chunk-PHX4SBOD.js.map +1 -0
- package/dist/index.cjs +243 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +36 -4
- package/dist/index.d.ts +36 -4
- package/dist/index.js +98 -31
- package/dist/index.js.map +1 -1
- package/dist/registry/index.d.cts +52 -3
- package/dist/registry/index.d.ts +52 -3
- package/dist/registry.cjs +111 -74
- package/dist/registry.cjs.map +1 -1
- package/dist/registry.js +1 -1
- package/dist/runtime/index.d.cts +61 -1
- package/dist/runtime/index.d.ts +61 -1
- package/dist/runtime.cjs +112 -1
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.js +1 -1
- package/package.json +6 -3
- package/dist/chunk-532A5QA3.js.map +0 -1
- package/dist/chunk-MFMRTRPO.js.map +0 -1
|
@@ -7,6 +7,40 @@ import { getWorkflowResolver, isResolutionFailure, getLlmClient } from './chunk-
|
|
|
7
7
|
import { memo, useMemo, createElement } from 'react';
|
|
8
8
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
9
9
|
|
|
10
|
+
// src/registry/connection.ts
|
|
11
|
+
var ANY_PORT_TYPE = "any";
|
|
12
|
+
var defaultPortCompatibility = (source, target) => {
|
|
13
|
+
const s = source?.type;
|
|
14
|
+
const t = target?.type;
|
|
15
|
+
if (!s || !t) return true;
|
|
16
|
+
if (s === ANY_PORT_TYPE || t === ANY_PORT_TYPE) return true;
|
|
17
|
+
return s === t;
|
|
18
|
+
};
|
|
19
|
+
function portsFor(node, side) {
|
|
20
|
+
const kind = getNodeKind(node.data?.kind ?? node.type);
|
|
21
|
+
const resolved = resolveNodePorts(node, kind ?? void 0);
|
|
22
|
+
return resolved[side] ?? [];
|
|
23
|
+
}
|
|
24
|
+
function findPort(ports, handleId) {
|
|
25
|
+
if (handleId == null) return ports.length === 1 ? ports[0] : void 0;
|
|
26
|
+
return ports.find((p) => p.id === handleId);
|
|
27
|
+
}
|
|
28
|
+
function createConnectionValidator(getNodes, options = {}) {
|
|
29
|
+
const compatible = options.compatible ?? defaultPortCompatibility;
|
|
30
|
+
return (connection) => {
|
|
31
|
+
const { source, target, sourceHandle, targetHandle } = connection;
|
|
32
|
+
if (!source || !target) return false;
|
|
33
|
+
if (!options.allowSelfConnection && source === target) return false;
|
|
34
|
+
const nodes = getNodes();
|
|
35
|
+
const src = nodes.find((n) => n.id === source);
|
|
36
|
+
const tgt = nodes.find((n) => n.id === target);
|
|
37
|
+
if (!src || !tgt) return false;
|
|
38
|
+
const outPort = findPort(portsFor(src, "outputs"), sourceHandle);
|
|
39
|
+
const inPort = findPort(portsFor(tgt, "inputs"), targetHandle);
|
|
40
|
+
return compatible(outPort, inPort);
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
10
44
|
// src/registry/subflow.ts
|
|
11
45
|
var DEFAULT_MAX_DEPTH = 8;
|
|
12
46
|
function subflowMode(config) {
|
|
@@ -1016,6 +1050,6 @@ function buildNodeTypes() {
|
|
|
1016
1050
|
return map;
|
|
1017
1051
|
}
|
|
1018
1052
|
|
|
1019
|
-
export { BUILTIN_KINDS, DEFAULT_MAX_DEPTH, RegistryNode, buildNodeTypes, declaredRoutes, llmRouterExecutor, registerBuiltinKinds, resolveFallbackPort, subflowExecutor, subflowMode, subflowPorts };
|
|
1020
|
-
//# sourceMappingURL=chunk-
|
|
1021
|
-
//# sourceMappingURL=chunk-
|
|
1053
|
+
export { ANY_PORT_TYPE, BUILTIN_KINDS, DEFAULT_MAX_DEPTH, RegistryNode, buildNodeTypes, createConnectionValidator, declaredRoutes, defaultPortCompatibility, llmRouterExecutor, registerBuiltinKinds, resolveFallbackPort, subflowExecutor, subflowMode, subflowPorts };
|
|
1054
|
+
//# sourceMappingURL=chunk-FSC64BPD.js.map
|
|
1055
|
+
//# sourceMappingURL=chunk-FSC64BPD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/registry/connection.ts","../src/registry/subflow.ts","../src/registry/llm-router.ts","../src/registry/RegistryNode.tsx","../src/registry/builtin.ts","../src/registry/index.ts"],"names":[],"mappings":"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","file":"chunk-FSC64BPD.js","sourcesContent":["import type { Connection, Edge } from \"@xyflow/react\";\nimport type { FlowNode, PortDescriptor } from \"../types\";\nimport { getNodeKind } from \"./registry\";\nimport { resolveNodePorts } from \"./ports\";\n\n/**\n * Connection validation — the single rule that decides whether an edge between\n * two ports is allowed. Lives here (React-free, registry-adjacent) so BOTH the\n * canvas (`<FlowCanvas isValidConnection>`) and the agent bridge's\n * `flow_connect` tool call the same function: a connection the canvas refuses\n * is a connection an agent cannot sneak past, and vice versa — no drift.\n *\n * `PortDescriptor.type` has always documented itself as being \"for hosts that\n * want to validate connections\", but nothing consumed it. This wires it up.\n */\n\n/**\n * Wildcard port type — matches any other type. A port that declares no `type`\n * is treated as a wildcard too, so existing flows (whose ports are untyped)\n * validate exactly as before.\n */\nexport const ANY_PORT_TYPE = \"any\";\n\n/** Decides whether a source-output port may feed a target-input port. */\nexport type PortCompatibility = (\n source: PortDescriptor | undefined,\n target: PortDescriptor | undefined,\n) => boolean;\n\n/**\n * Default compatibility rule: allow the connection UNLESS both ports declare a\n * concrete, differing type. An absent type or the `any` wildcard matches\n * anything — so typed ports get enforced while untyped ports stay permissive,\n * making this a safe default that never breaks an existing untyped graph.\n */\nexport const defaultPortCompatibility: PortCompatibility = (source, target) => {\n const s = source?.type;\n const t = target?.type;\n if (!s || !t) return true;\n if (s === ANY_PORT_TYPE || t === ANY_PORT_TYPE) return true;\n return s === t;\n};\n\nexport type ConnectionValidatorOptions = {\n /** Override the type-compatibility rule. Defaults to {@link defaultPortCompatibility}. */\n compatible?: PortCompatibility;\n /**\n * Allow a node's own output to feed its own input (a self-loop). Default\n * false — self-connections are almost always an accident, and the rare flow\n * that wants one can opt in.\n */\n allowSelfConnection?: boolean;\n};\n\n/** Resolve a node's effective ports for one side, going through the registry. */\nfunction portsFor(node: FlowNode, side: \"inputs\" | \"outputs\"): PortDescriptor[] {\n const kind = getNodeKind((node.data as any)?.kind ?? node.type);\n const resolved = resolveNodePorts(node, kind ?? undefined);\n return resolved[side] ?? [];\n}\n\n/**\n * Resolve which port a handle id refers to. When a side has a single port and\n * the handle id is absent (React Flow omits it for a lone default handle), use\n * that port; otherwise match by id.\n */\nfunction findPort(\n ports: PortDescriptor[],\n handleId: string | null | undefined,\n): PortDescriptor | undefined {\n if (handleId == null) return ports.length === 1 ? ports[0] : undefined;\n return ports.find((p) => p.id === handleId);\n}\n\n/**\n * Build an `isValidConnection` predicate that enforces port-type compatibility\n * against a live node list. Pass it straight to `<FlowCanvas isValidConnection>`\n * or reuse it to gate an agent's `flow_connect`.\n *\n * `getNodes` is called on every check so the validator always sees the current\n * graph (wire it to a ref/state getter, not a snapshot).\n *\n * A connection is rejected when: an endpoint is missing; it is a self-loop and\n * `allowSelfConnection` is off; either node is unknown; or the resolved ports\n * are type-incompatible. Nodes/ports with no declared type validate as before.\n */\nexport function createConnectionValidator(\n getNodes: () => FlowNode[],\n options: ConnectionValidatorOptions = {},\n): (connection: Connection | Edge) => boolean {\n const compatible = options.compatible ?? defaultPortCompatibility;\n return (connection) => {\n const { source, target, sourceHandle, targetHandle } = connection;\n if (!source || !target) return false;\n if (!options.allowSelfConnection && source === target) return false;\n\n const nodes = getNodes();\n const src = nodes.find((n) => n.id === source);\n const tgt = nodes.find((n) => n.id === target);\n if (!src || !tgt) return false;\n\n const outPort = findPort(portsFor(src, \"outputs\"), sourceHandle);\n const inPort = findPort(portsFor(tgt, \"inputs\"), targetHandle);\n return compatible(outPort, inPort);\n };\n}\n","import { getWorkflowResolver, isResolutionFailure } from \"./capabilities\";\nimport { runFlow } from \"../runtime/run-flow\";\nimport type { NodeExecutor, RunEvent } from \"../types\";\n\n/**\n * `@fancy/subflow` — run another workflow and bring its result home.\n *\n * Core, not marketplace: it introduces no third-party dependency. It runs a\n * child graph through the very same engine, so the only thing it needs from the\n * host is where workflows live (`registerWorkflowResolver`).\n *\n * Three output modes, because both halves are genuinely useful:\n *\n * - `output` — the child's outputs arrive on `out` when it finishes.\n * - `stream` — the child's events are forwarded live on `stream` as they\n * happen, so a parent can show progress instead of a spinner.\n * - `both` — stream while running AND deliver the final outputs.\n *\n * Recursion is guarded by depth. A workflow that references itself (directly or\n * through a chain) would otherwise recurse until the stack dies, which surfaces\n * as an opaque crash rather than \"you built a loop\".\n */\n\nexport const DEFAULT_MAX_DEPTH = 8;\n\nexport type SubflowMode = \"output\" | \"stream\" | \"both\";\n\nexport function subflowMode(config: Record<string, unknown>): SubflowMode {\n const mode = config.mode;\n return mode === \"stream\" || mode === \"both\" ? mode : \"output\";\n}\n\n/** Ports follow the mode — `stream` only exists when something streams. */\nexport function subflowPorts(config: Record<string, unknown>) {\n const mode = subflowMode(config);\n const ports = [{ id: \"out\", label: \"result\" }];\n if (mode === \"stream\" || mode === \"both\") ports.unshift({ id: \"stream\", label: \"stream\" });\n return ports;\n}\n\nexport const subflowExecutor: NodeExecutor = async (ctx) => {\n const config = ((ctx.node.data as any)?.config ?? {}) as Record<string, unknown>;\n const ref = String(config.workflow ?? \"\").trim();\n if (!ref) ctx.abort(\"subflow has no workflow reference configured\");\n\n const resolver = getWorkflowResolver();\n if (!resolver) {\n ctx.abort(\n \"No workflow resolver registered. Call registerWorkflowResolver() so subflow can find the workflow it references.\",\n );\n }\n\n const maxDepth = Number.isFinite(config.maxDepth) ? Number(config.maxDepth) : DEFAULT_MAX_DEPTH;\n const depth = ctx.depth ?? 0;\n if (depth + 1 > maxDepth) {\n // Name the cause. \"Maximum call stack exceeded\" tells an author nothing\n // about the workflow they wired into itself.\n ctx.abort(\n `subflow depth limit reached (${maxDepth}) at \"${ref}\" — a workflow is referencing itself, directly or through a chain.`,\n );\n }\n\n // An optional pin. A workflow another workflow depends on is an interface:\n // without a pin, someone edits the child and the parent silently runs\n // different logic while still reporting success.\n const pinned = config.version === undefined || config.version === \"\" ? undefined : Number(config.version);\n if (pinned !== undefined && !Number.isInteger(pinned)) {\n ctx.abort(`subflow \"${ref}\" has a non-integer version pin (${String(config.version)}).`);\n }\n\n const resolved = await resolver!(ref, pinned);\n\n // A mismatch names BOTH versions. Reporting it as \"not found\" would send an\n // author looking for a workflow that is sitting right there — which is why\n // the resolver can say which of the two failures it hit.\n const child = isResolutionFailure(resolved)\n ? ctx.abort(\n resolved.reason === \"version-mismatch\"\n ? (resolved.message ??\n `subflow \"${ref}\" is pinned to version ${pinned}, but the host has ${resolved.available ?? \"a different version\"}.`)\n : (resolved.message ?? `subflow could not resolve workflow \"${ref}\"`),\n )\n : resolved;\n\n if (!child) ctx.abort(`subflow could not resolve workflow \"${ref}\"`);\n\n const mode = subflowMode(config);\n const streaming = mode === \"stream\" || mode === \"both\";\n\n const forward = (event: RunEvent) => {\n if (!streaming) return;\n // Surface the child's progress on the PARENT's feed as a log line against\n // this node. Re-emitting the child's raw events would collide with the\n // parent's own node ids — a child's \"node-status\" for its `output` node is\n // not a status for anything in the parent graph.\n const detail =\n event.type === \"node-status\"\n ? `${event.nodeId} ${event.status}`\n : event.type === \"run-end\"\n ? `finished (${event.ok ? \"ok\" : \"failed\"})`\n : event.type;\n ctx.emit({\n type: \"log\",\n nodeId: ctx.node.id,\n level: \"info\",\n message: `[${ref}] ${detail}`,\n });\n };\n\n const result = await runFlow(\n child!,\n (config.executors as never) ?? {},\n forward,\n {\n initialInputs: (config.inputs as Record<string, Record<string, unknown>>) ?? {\n // With no explicit mapping, hand the parent's inputs to the child's\n // entry points — the obvious default, and it makes the simple case\n // require no configuration at all.\n __parent: ctx.inputs as Record<string, unknown>,\n },\n depth: depth + 1,\n },\n );\n\n if (!result.ok) {\n ctx.abort(`subflow \"${ref}\" failed: ${result.error ?? \"unknown error\"}`);\n }\n\n // `stream` alone still emits a final value on `stream` so downstream nodes\n // have something to run on; `both` publishes on every declared port.\n if (mode === \"stream\") {\n return { __port: \"stream\", value: result.outputs };\n }\n if (mode === \"both\") {\n return result.outputs;\n }\n return { __port: \"out\", value: result.outputs };\n};\n","import { getLlmClient, type LlmRoute } from \"./capabilities\";\nimport type { NodeExecutor } from \"../types\";\n\n/**\n * `@fancy/llm_branch` — a SHUTTLE, not an engine.\n *\n * It carries the declared routes and the decision prompt out to whatever LLM\n * client the host registered, and carries the chosen port back down the graph.\n * It contains no provider SDK, no prompt engineering, no response parsing and\n * no retry policy — all of that belongs to the host's client, which is what\n * lets this node live in core without every consumer inheriting an LLM\n * dependency.\n *\n * The one thing it does own is graph integrity, because that is a workflow\n * concern rather than an AI one: a port the model invents must never route.\n */\n\n/** Read the node's declared routes out of config. */\nexport function declaredRoutes(config: Record<string, unknown>): LlmRoute[] {\n const raw = config.routes;\n if (!Array.isArray(raw)) return [];\n return raw\n .map((r) => ({ port: String((r as any)?.port ?? \"\").trim(), description: (r as any)?.description }))\n .filter((r) => r.port !== \"\");\n}\n\n/**\n * Where a run goes when the model returns a port that was never offered.\n *\n * Emitting on a port with no edge silently ends the branch — the worst failure\n * mode in a workflow engine, because the run reports success having done\n * nothing. So: the `fallback` port when it exists, else the first declared\n * route, and always loudly.\n */\nexport function resolveFallbackPort(routes: LlmRoute[], fallbackEnabled: boolean): string {\n if (fallbackEnabled) return \"fallback\";\n // Callers only reach this with at least one declared route (a node with none\n // aborts earlier), so there is always somewhere safe to land.\n return routes[0]?.port ?? \"out\";\n}\n\nexport const llmRouterExecutor: NodeExecutor = async (ctx) => {\n const config = ((ctx.node.data as any)?.config ?? {}) as Record<string, unknown>;\n const routes = declaredRoutes(config);\n\n if (routes.length === 0) {\n ctx.abort(\"llm_router has no routes configured\");\n }\n\n const client = getLlmClient();\n if (!client) {\n // Fail loudly rather than guessing a branch. A silent default here would\n // look like the model made a choice.\n ctx.abort(\n \"No LLM client registered. Call registerLlmClient() with your provider adapter — fancy-flow ships the routing, not the model call.\",\n );\n }\n\n const fallbackEnabled = config.fallback !== false;\n\n const choice = await client!.chooseRoute({\n system: typeof config.system === \"string\" ? config.system : undefined,\n prompt: String(config.prompt ?? ctx.inputs ?? \"\"),\n routes,\n provider: typeof config.provider === \"string\" ? config.provider : undefined,\n model: typeof config.model === \"string\" ? config.model : undefined,\n credential: typeof config.credential === \"string\" ? config.credential : undefined,\n });\n\n const offered = new Set(routes.map((r) => r.port));\n let port = choice?.port ?? \"\";\n let reason = choice?.reason;\n\n if (!offered.has(port)) {\n const safe = resolveFallbackPort(routes, fallbackEnabled);\n ctx.emit({\n type: \"log\",\n nodeId: ctx.node.id,\n level: \"warn\",\n message: `llm_router: model returned \"${port || \"(nothing)\"}\", which is not a declared route. Routing to \"${safe}\".`,\n });\n reason = reason ?? `unrecognised route \"${port}\"`;\n port = safe;\n }\n\n // The reason travels WITH the value, so a completed run explains itself\n // without needing the model call replayed.\n return { __port: port, value: { route: port, reason, input: ctx.inputs } };\n};\n","import { memo, useMemo } from \"react\";\nimport { Handle, Position, type NodeProps } from \"@xyflow/react\";\nimport type { FlowNode, NodeRunStatus, PortDescriptor } from \"../types\";\nimport { categoryAccent, getNodeKind } from \"./registry\";\nimport { nodeConfig, resolveNodePorts } from \"./ports\";\n\n/**\n * RegistryNode — generic node renderer that looks up the node's kind in\n * the registry and applies its `accent`/`label`/`icon`/`renderBody`. Used\n * as the xyflow node component for every registered kind.\n */\nfunction RegistryNodeInner(props: NodeProps<FlowNode>) {\n const kindName = (props.data as any).kind ?? props.type;\n const kind = useMemo(() => getNodeKind(kindName), [kindName]);\n\n if (!kind) {\n return (\n <div className=\"ff-node ff-node--unknown\">\n <div className=\"ff-node__header\" style={{ background: \"#71717a\" }}>\n <span className=\"ff-node__tag\">UNKNOWN</span>\n <span className=\"ff-node__label\">{kindName}</span>\n </div>\n <p className=\"ff-node__desc\">No registered kind for \"{kindName}\".</p>\n </div>\n );\n }\n\n const data = props.data;\n const status: NodeRunStatus = data.status ?? \"idle\";\n const accent = kind.accent ?? categoryAccent(kind.category);\n const resolved = resolveNodePorts(props, kind);\n const inputs: PortDescriptor[] = resolved.inputs ?? defaultInputs(kind.category);\n const outputs: PortDescriptor[] = resolved.outputs ?? defaultOutputs(kind.category);\n const config = nodeConfig(props);\n const label = data.label ?? kind.label;\n\n return (\n <div\n className={[\n \"ff-node\",\n `ff-node--status-${status}`,\n `ff-node--cat-${kind.category}`,\n props.selected ? \"ff-node--selected\" : \"\",\n ].filter(Boolean).join(\" \")}\n style={{ borderColor: props.selected ? accent : undefined }}\n >\n <header className=\"ff-node__header\" style={{ background: accent }}>\n {kind.icon && <span className=\"ff-node__icon\" aria-hidden>{kind.icon}</span>}\n <span className=\"ff-node__tag\">{kind.label.toUpperCase()}</span>\n <span className=\"ff-node__label\">{label}</span>\n {status !== \"idle\" && <span className={`ff-node__dot ff-node__dot--${status}`} aria-label={`status ${status}`} />}\n </header>\n\n {data.description && <p className=\"ff-node__desc\">{data.description}</p>}\n\n <div className=\"ff-node__body\">\n {kind.renderBody\n ? kind.renderBody({ nodeId: props.id, config: config as any, selected: props.selected ?? false })\n : <DefaultBody config={config} kind={kind.configSchema} />}\n </div>\n\n {data.statusText && <p className=\"ff-node__status-text\">{data.statusText}</p>}\n\n {inputs.map((p, i) => (\n <Handle\n key={p.id}\n type=\"target\"\n position={Position.Left}\n id={p.id}\n style={portStyle(i, inputs.length)}\n title={p.label ?? p.id}\n />\n ))}\n {outputs.map((p, i) => (\n <Handle\n key={p.id}\n type=\"source\"\n position={Position.Right}\n id={p.id}\n style={portStyle(i, outputs.length)}\n title={p.label ?? p.id}\n />\n ))}\n </div>\n );\n}\n\nexport const RegistryNode = memo(RegistryNodeInner);\n\nfunction defaultInputs(category: string): PortDescriptor[] {\n return category === \"trigger\" ? [] : [{ id: \"in\" }];\n}\nfunction defaultOutputs(category: string): PortDescriptor[] {\n return category === \"output\" ? [] : [{ id: \"out\" }];\n}\n\nfunction portStyle(i: number, total: number): React.CSSProperties {\n if (total <= 1) return {};\n const slot = (100 / (total + 1)) * (i + 1);\n return { top: `${slot}%` };\n}\n\n/**\n * DefaultBody — compact summary of the config values for nodes that\n * don't provide a custom renderBody. Skips fields that look empty.\n */\nfunction DefaultBody({ config, kind }: { config: Record<string, unknown>; kind?: import(\"./types\").ConfigField[] }) {\n const fields = kind ?? [];\n const visible = fields\n .map((f) => ({ field: f, value: config[f.key] }))\n .filter(({ value }) => value !== undefined && value !== \"\" && value !== null);\n if (visible.length === 0) {\n return <div className=\"ff-node__body-empty\">— configure in the panel</div>;\n }\n return (\n <ul className=\"ff-node__summary\">\n {visible.slice(0, 4).map(({ field, value }) => (\n <li key={field.key}>\n <span className=\"ff-node__summary-key\">{field.label}:</span>\n <span className=\"ff-node__summary-value\">{previewValue(value)}</span>\n </li>\n ))}\n {visible.length > 4 && <li className=\"ff-node__summary-more\">+ {visible.length - 4} more</li>}\n </ul>\n );\n}\n\nconst truncate = (s: string, n = 30): string => (s.length > n ? s.slice(0, n - 1) + \"…\" : s);\n\n/** A short, human name for one item in a repeater/list value. */\nfunction itemLabel(item: unknown): string {\n if (item && typeof item === \"object\") {\n const o = item as Record<string, unknown>;\n const name = o.label ?? o.name ?? o.key ?? o.title ?? o.id;\n if (typeof name === \"string\" && name) return name;\n if (typeof name === \"number\") return String(name);\n return \"item\";\n }\n return String(item ?? \"\");\n}\n\n/**\n * A node card's job is to read at a glance, not to be a data dump — so a value\n * is summarised, never `JSON.stringify`d. An array becomes its item names (or a\n * count), an object becomes a field count. Raw JSON on a card was the specific\n * thing to kill: `Fields: [{\"key\":\"answer\",…}]` reads as noise.\n */\nexport function previewValue(v: unknown): string {\n if (v === null || v === undefined) return \"\";\n if (typeof v === \"string\") return truncate(v);\n if (typeof v === \"number\" || typeof v === \"boolean\") return String(v);\n if (Array.isArray(v)) {\n if (v.length === 0) return \"none\";\n const names = v.slice(0, 3).map(itemLabel).filter(Boolean).join(\", \");\n const rest = v.length > 3 ? `, +${v.length - 3}` : \"\";\n return names ? truncate(names + rest) : `${v.length} item${v.length === 1 ? \"\" : \"s\"}`;\n }\n if (typeof v === \"object\") {\n const keys = Object.keys(v as object);\n return keys.length === 0 ? \"empty\" : `${keys.length} field${keys.length === 1 ? \"\" : \"s\"}`;\n }\n return \"…\";\n}\n","import { createElement } from \"react\";\nimport { registerNodeKind } from \"./registry\";\nimport { RichInputPreview } from \"./rich-input\";\nimport { llmRouterExecutor } from \"./llm-router\";\nimport { subflowExecutor, subflowPorts, DEFAULT_MAX_DEPTH } from \"./subflow\";\nimport type { PortDescriptor } from \"../types\";\nimport type { ConfigField, NodeKindDefinition } from \"./types\";\n\n/**\n * Built-in agentic node kit. Every kind ships with schema + UI but\n * NO executor — host apps wire executors per kind so they control where\n * memory, data, network, and AI calls actually go.\n */\n\n/**\n * Ports for `switch_case`, derived from its `cases` map (match value → port).\n *\n * Several match values may route to the same port, so ports are de-duplicated\n * and labelled with every value that reaches them (\"a|c\"). `default` is always\n * present — unmatched input has to land somewhere.\n */\nfunction casePorts(cases: unknown): PortDescriptor[] {\n const byPort = new Map<string, string[]>();\n if (cases && typeof cases === \"object\" && !Array.isArray(cases)) {\n for (const [match, port] of Object.entries(cases as Record<string, unknown>)) {\n if (typeof port !== \"string\" || port === \"\" || port === \"default\") continue;\n const matches = byPort.get(port) ?? [];\n matches.push(match);\n byPort.set(port, matches);\n }\n }\n const ports: PortDescriptor[] = [...byPort].map(([id, matches]) => ({\n id,\n label: matches.join(\"|\"),\n }));\n return [...ports, { id: \"default\", label: \"default\" }];\n}\n\n/**\n * Ports for `llm_branch`, derived from its `routes` list. Blank and duplicate\n * port names are dropped so a half-typed route can't collide with a real one.\n */\nfunction routePorts(routes: unknown, fallback?: unknown): PortDescriptor[] {\n const ports: PortDescriptor[] = [];\n const seen = new Set<string>();\n if (Array.isArray(routes)) {\n for (const route of routes) {\n const id = (route as any)?.port;\n if (typeof id !== \"string\" || id.trim() === \"\" || seen.has(id)) continue;\n seen.add(id);\n ports.push({ id, label: id });\n }\n }\n if (fallback !== false && !seen.has(\"fallback\")) {\n ports.push({ id: \"fallback\", label: \"fallback\" });\n }\n if (ports.length === 0) ports.push({ id: \"out\" });\n return ports;\n}\n\nconst HTTP_METHODS: ConfigField[] = [\n { type: \"select\", key: \"method\", label: \"Method\", options: [\n { value: \"GET\", label: \"GET\" },\n { value: \"POST\", label: \"POST\" },\n { value: \"PUT\", label: \"PUT\" },\n { value: \"PATCH\", label: \"PATCH\" },\n { value: \"DELETE\", label: \"DELETE\" },\n ], default: \"GET\", required: true },\n];\n\nconst KINDS: NodeKindDefinition[] = [\n // ───────────── Triggers ─────────────\n {\n name: \"@particle-academy/manual_trigger\",\n aliases: [\"manual_trigger\", \"@fancy/manual_trigger\"],\n category: \"trigger\",\n label: \"Manual\",\n description: \"Entry point fired when the user clicks Run.\",\n icon: \"⚡\",\n inputs: [],\n outputs: [{ id: \"out\" }],\n },\n {\n name: \"@particle-academy/webhook_trigger\",\n aliases: [\"webhook_trigger\", \"@fancy/webhook_trigger\"],\n category: \"trigger\",\n label: \"Webhook\",\n description: \"Triggered by an inbound HTTP request to a host-provided URL.\",\n icon: \"📡\",\n inputs: [],\n outputs: [{ id: \"out\", label: \"payload\" }],\n configSchema: [\n { type: \"text\", key: \"path\", label: \"Path\", placeholder: \"/hooks/my-flow\", required: true },\n { type: \"select\", key: \"method\", label: \"Method\", options: [\n { value: \"POST\", label: \"POST\" }, { value: \"GET\", label: \"GET\" },\n ], default: \"POST\" },\n { type: \"credential\", key: \"secret\", label: \"Verifying secret\", credentialType: \"webhook_secret\" },\n ],\n },\n {\n name: \"@particle-academy/schedule_trigger\",\n aliases: [\"schedule_trigger\", \"@fancy/schedule_trigger\"],\n category: \"trigger\",\n label: \"Schedule\",\n description: \"Fires on a cron schedule (host-implemented).\",\n icon: \"⏱\",\n inputs: [],\n outputs: [{ id: \"out\" }],\n configSchema: [\n { type: \"text\", key: \"cron\", label: \"Cron\", placeholder: \"*/5 * * * *\", required: true,\n description: \"Standard 5-field cron expression.\" },\n { type: \"text\", key: \"timezone\", label: \"Timezone\", placeholder: \"UTC\", default: \"UTC\" },\n ],\n },\n {\n name: \"@particle-academy/user_input\",\n aliases: [\"user_input\", \"@fancy/user_input\"],\n pausesForHuman: \"input\",\n category: \"human\",\n label: \"User Input\",\n description: \"Pause the flow until the user submits the configured form.\",\n icon: \"✎\",\n inputs: [{ id: \"in\" }],\n outputs: [{ id: \"out\", label: \"values\" }],\n configSchema: [\n { type: \"text\", key: \"title\", label: \"Form title\", default: \"Need your input\" },\n {\n type: \"repeater\",\n key: \"fields\",\n label: \"Fields\",\n description: \"The form the run pauses on.\",\n titleKey: \"label\",\n addLabel: \"Add field\",\n minItems: 1,\n fields: [\n { type: \"text\", key: \"key\", label: \"Key\", required: true, placeholder: \"answer\" },\n { type: \"text\", key: \"label\", label: \"Label\", required: true, placeholder: \"Your answer\" },\n {\n type: \"select\", key: \"type\", label: \"Type\", default: \"text\",\n options: [\n { value: \"text\", label: \"Text\" },\n { value: \"textarea\", label: \"Long text\" },\n { value: \"number\", label: \"Number\" },\n { value: \"select\", label: \"Select\" },\n { value: \"switch\", label: \"Switch\" },\n ],\n },\n { type: \"switch\", key: \"required\", label: \"Required\", default: false },\n ],\n default: [{ key: \"answer\", label: \"Your answer\", type: \"textarea\", required: true }],\n },\n ],\n },\n\n {\n name: \"@particle-academy/rich_user_input\",\n aliases: [\"rich_user_input\", \"@fancy/rich_user_input\"],\n pausesForHuman: \"input\",\n category: \"human\",\n label: \"Rich User Input\",\n description: \"Pause the flow on a fully authored page — content, required reading, multi-section forms.\",\n icon: \"▤\",\n inputs: [{ id: \"in\" }],\n outputs: [{ id: \"out\", label: \"values\" }],\n configSchema: [\n { type: \"text\", key: \"title\", label: \"Step title\", default: \"Please review\" },\n {\n type: \"document\",\n key: \"document\",\n label: \"Page content\",\n documentType: \"stages\",\n description: \"Authored with the host's document editor (fancy-cms Stages).\",\n },\n { type: \"switch\", key: \"requireConfirm\", label: \"Require explicit confirmation\", default: true },\n { type: \"text\", key: \"submitLabel\", label: \"Submit button\", default: \"Continue\" },\n ],\n // Preview the authored page inside a FauxClient frame, so the canvas shows\n // what the person hitting this step will actually see.\n renderBody: (ctx) => createElement(RichInputPreview, { config: (ctx.config ?? {}) as Record<string, unknown> }),\n },\n\n {\n name: \"@particle-academy/subflow\",\n aliases: [\"subflow\", \"@fancy/subflow\"],\n category: \"logic\",\n label: \"SubFlow\",\n description: \"Run another workflow and bring its result — or its live progress — back into this one.\",\n icon: \"⧉\",\n inputs: [{ id: \"in\" }],\n // The stream port only exists when something actually streams.\n outputs: (config: any) => subflowPorts(config ?? {}),\n // Core, not marketplace: it runs a child graph through this same engine and\n // needs nothing from outside except where workflows live.\n executor: subflowExecutor,\n configSchema: [\n { type: \"text\", key: \"workflow\", label: \"Workflow\", required: true,\n placeholder: \"onboarding-v2\",\n description: \"Reference resolved by the host's registerWorkflowResolver().\" },\n { type: \"number\", key: \"version\", label: \"Pin to version\",\n description: \"Optional. Leave blank to always run the child's current version. Pinning fails the run loudly if the child has moved on — without it, someone edits the child and this flow silently runs different logic.\" },\n {\n type: \"select\", key: \"mode\", label: \"Return\", default: \"output\",\n options: [\n { value: \"output\", label: \"Output when it finishes\" },\n { value: \"stream\", label: \"Stream progress as it runs\" },\n { value: \"both\", label: \"Both — stream, then output\" },\n ],\n description: \"Streaming adds a second port so a parent can show progress instead of a spinner.\",\n },\n { type: \"keyvalue\", key: \"inputs\", label: \"Input mapping\",\n description: \"Values handed to the child's entry points. Omit to pass this node's inputs straight through.\",\n keyLabel: \"Name\", valueLabel: \"Value\", addLabel: \"Add input\" },\n { type: \"number\", key: \"maxDepth\", label: \"Max nesting depth\", default: DEFAULT_MAX_DEPTH, min: 1, max: 32,\n description: \"Guards against a workflow referencing itself.\" },\n ],\n },\n\n // ───────────── Logic ─────────────\n {\n name: \"@particle-academy/branch\",\n aliases: [\"branch\", \"@fancy/branch\"],\n category: \"logic\",\n label: \"Branch\",\n description: \"Multi-way branch on a condition or value.\",\n icon: \"◇\",\n inputs: [{ id: \"in\" }],\n outputs: [{ id: \"true\", label: \"true\" }, { id: \"false\", label: \"false\" }],\n configSchema: [\n {\n type: \"select\", key: \"match\", label: \"Match\", default: \"all\",\n options: [\n { value: \"all\", label: \"All conditions (AND)\" },\n { value: \"any\", label: \"Any condition (OR)\" },\n ],\n },\n {\n type: \"repeater\",\n key: \"conditions\",\n label: \"Conditions\",\n description: \"Routes to `true` when these match, otherwise `false`.\",\n titleKey: \"left\",\n addLabel: \"Add condition\",\n minItems: 1,\n fields: [\n { type: \"expression\", key: \"left\", label: \"Value\", example: \"{{ $json.status }}\", required: true },\n {\n type: \"select\", key: \"operator\", label: \"Is\", default: \"eq\",\n options: [\n { value: \"eq\", label: \"equal to\" },\n { value: \"neq\", label: \"not equal to\" },\n { value: \"contains\", label: \"contains\" },\n { value: \"not_contains\", label: \"does not contain\" },\n { value: \"gt\", label: \"greater than\" },\n { value: \"gte\", label: \"greater than or equal to\" },\n { value: \"lt\", label: \"less than\" },\n { value: \"lte\", label: \"less than or equal to\" },\n { value: \"truthy\", label: \"true\" },\n { value: \"falsy\", label: \"false\" },\n { value: \"empty\", label: \"empty\" },\n { value: \"not_empty\", label: \"not empty\" },\n ],\n },\n { type: \"text\", key: \"right\", label: \"Compared to\", placeholder: \"active\" },\n ],\n default: [{ left: \"\", operator: \"eq\", right: \"\" }],\n },\n {\n type: \"expression\",\n key: \"condition\",\n label: \"Raw expression (advanced)\",\n example: \"{{ $json.active && $json.score > 10 }}\",\n description: \"Escape hatch for logic the builder can't express. Overrides the conditions above when set.\",\n },\n ],\n },\n {\n name: \"@particle-academy/switch_case\",\n aliases: [\"switch_case\", \"@fancy/switch_case\"],\n category: \"logic\",\n label: \"Switch\",\n description: \"Route to one of N labelled outputs based on a key.\",\n icon: \"⤳\",\n inputs: [{ id: \"in\" }],\n // Ports ARE the config: every distinct port a case routes to becomes an\n // output handle, plus the always-present `default`. Editing the cases map\n // moves the ports on the canvas and the ports the runtime activates.\n outputs: (config: any) => casePorts(config?.cases),\n configSchema: [\n { type: \"expression\", key: \"value\", label: \"Switch on\", example: \"{{ $json.kind }}\", required: true },\n {\n type: \"keyvalue\",\n key: \"cases\",\n label: \"Cases\",\n description: \"Match value → output port. Unmatched input takes `default`.\",\n keyLabel: \"When value is\",\n valueLabel: \"Route to port\",\n keyPlaceholder: \"a\",\n valuePlaceholder: \"case_a\",\n addLabel: \"Add case\",\n default: { a: \"case_a\", b: \"case_b\" },\n },\n ],\n },\n {\n name: \"@particle-academy/for_each\",\n aliases: [\"for_each\", \"@fancy/for_each\"],\n category: \"logic\",\n label: \"For Each\",\n description: \"Iterate over a list, emitting each item on `item`.\",\n icon: \"↻\",\n inputs: [{ id: \"in\" }],\n outputs: [{ id: \"item\", label: \"item\" }, { id: \"done\", label: \"done\" }],\n configSchema: [\n { type: \"expression\", key: \"source\", label: \"List\", example: \"{{ $json.users }}\", required: true },\n { type: \"number\", key: \"concurrency\", label: \"Concurrency\", default: 1, min: 1, max: 50 },\n ],\n },\n {\n name: \"@particle-academy/merge\",\n aliases: [\"merge\", \"@fancy/merge\"],\n category: \"logic\",\n label: \"Merge\",\n description: \"Combine multiple inputs into one object or array.\",\n icon: \"⊕\",\n inputs: [{ id: \"a\" }, { id: \"b\" }],\n outputs: [{ id: \"out\" }],\n configSchema: [\n { type: \"select\", key: \"mode\", label: \"Mode\", default: \"merge\",\n options: [{ value: \"merge\", label: \"Object merge\" }, { value: \"concat\", label: \"Array concat\" }] },\n ],\n },\n {\n name: \"@particle-academy/wait\",\n aliases: [\"wait\", \"@fancy/wait\"],\n category: \"logic\",\n label: \"Wait\",\n description: \"Sleep or wait for an external event.\",\n icon: \"⏸\",\n configSchema: [\n { type: \"select\", key: \"mode\", label: \"Mode\", default: \"duration\",\n options: [{ value: \"duration\", label: \"Duration\" }, { value: \"until\", label: \"Until timestamp\" }, { value: \"event\", label: \"External event\" }] },\n { type: \"text\", key: \"duration\", label: \"Duration\", placeholder: \"5s, 10m, 1h\", description: \"Used when mode = duration.\" },\n ],\n },\n {\n name: \"@particle-academy/transform\",\n aliases: [\"transform\", \"@fancy/transform\"],\n category: \"logic\",\n label: \"Transform\",\n description: \"Reshape data with an expression.\",\n icon: \"ƒ\",\n configSchema: [\n {\n type: \"select\", key: \"mode\", label: \"Build the output\", default: \"fields\",\n options: [\n { value: \"fields\", label: \"Field by field\" },\n { value: \"expression\", label: \"One expression\" },\n ],\n },\n {\n type: \"repeater\",\n key: \"fields\",\n label: \"Output fields\",\n description: \"Each row becomes a key on the result.\",\n titleKey: \"key\",\n addLabel: \"Add field\",\n fields: [\n { type: \"text\", key: \"key\", label: \"Key\", required: true, placeholder: \"name\" },\n { type: \"expression\", key: \"value\", label: \"Value\", example: \"{{ $json.first }}\", required: true },\n ],\n default: [{ key: \"\", value: \"\" }],\n },\n {\n type: \"expression\",\n key: \"expression\",\n label: \"Expression (advanced)\",\n example: \"{{ { id: $json.id, name: $json.first + ' ' + $json.last } }}\",\n description: \"Used when the mode above is set to one expression.\",\n },\n ],\n },\n\n // ───────────── Data ─────────────\n {\n name: \"@particle-academy/memory_store\",\n aliases: [\"memory_store\", \"@fancy/memory_store\"],\n category: \"data\",\n label: \"Memory Store\",\n description: \"Read or write per-conversation memory.\",\n icon: \"🧠\",\n configSchema: [\n { type: \"select\", key: \"operation\", label: \"Operation\", required: true, default: \"read\",\n options: [{ value: \"read\", label: \"Read\" }, { value: \"write\", label: \"Write\" }, { value: \"append\", label: \"Append\" }] },\n { type: \"text\", key: \"key\", label: \"Key\", placeholder: \"user.preferences\", required: true },\n { type: \"expression\", key: \"value\", label: \"Value (write/append only)\", example: \"{{ $json }}\" },\n { type: \"credential\", key: \"store\", label: \"Memory store\", credentialType: \"memory_store\" },\n ],\n },\n {\n name: \"@particle-academy/data_store\",\n aliases: [\"data_store\", \"@fancy/data_store\"],\n category: \"data\",\n label: \"Data Store\",\n description: \"Key-value or table read/write against a host store.\",\n icon: \"🗃\",\n configSchema: [\n { type: \"select\", key: \"operation\", label: \"Operation\", required: true, default: \"get\",\n options: [\n { value: \"get\", label: \"Get\" }, { value: \"set\", label: \"Set\" }, { value: \"delete\", label: \"Delete\" },\n { value: \"query\", label: \"Query\" }, { value: \"list\", label: \"List\" },\n ] },\n { type: \"text\", key: \"table\", label: \"Table / collection\", required: true },\n { type: \"text\", key: \"key\", label: \"Key\" },\n { type: \"keyvalue\", key: \"where\", label: \"Where\",\n description: \"Field/value pairs to match. For query and list operations.\",\n keyLabel: \"Field\", valueLabel: \"Equals\", addLabel: \"Add filter\" },\n { type: \"expression\", key: \"value\", label: \"Value (set only)\", example: \"{{ $json }}\" },\n { type: \"credential\", key: \"store\", label: \"Data store\", credentialType: \"data_store\" },\n ],\n },\n {\n name: \"@particle-academy/variable\",\n aliases: [\"variable\", \"@fancy/variable\"],\n category: \"data\",\n label: \"Variable\",\n description: \"Workflow-scoped value used by other nodes.\",\n icon: \"𝓍\",\n configSchema: [\n { type: \"text\", key: \"name\", label: \"Name\", required: true },\n { type: \"expression\", key: \"value\", label: \"Value\", required: true },\n ],\n },\n\n // ───────────── AI ─────────────\n {\n name: \"@particle-academy/llm_call\",\n aliases: [\"llm_call\", \"@fancy/llm_call\"],\n category: \"ai\",\n label: \"LLM Call\",\n description: \"Send a prompt + context to a model and receive a response.\",\n icon: \"✦\",\n configSchema: [\n { type: \"select\", key: \"provider\", label: \"Provider\", default: \"anthropic\",\n options: [\n { value: \"anthropic\", label: \"Anthropic\" },\n { value: \"openai\", label: \"OpenAI\" },\n { value: \"custom\", label: \"Custom\" },\n ] },\n { type: \"text\", key: \"model\", label: \"Model\", placeholder: \"claude-sonnet-4-5\", required: true },\n { type: \"textarea\", key: \"system\", label: \"System prompt\", rows: 4 },\n { type: \"expression\", key: \"prompt\", label: \"User prompt\", example: \"{{ $json.question }}\", required: true },\n { type: \"number\", key: \"temperature\", label: \"Temperature\", min: 0, max: 2, step: 0.1, default: 0.7 },\n { type: \"number\", key: \"max_tokens\", label: \"Max tokens\", min: 1, max: 8192, default: 1024 },\n {\n type: \"repeater\", key: \"tools\", label: \"Tools\",\n description: \"Tools the model may call.\",\n titleKey: \"name\", addLabel: \"Add tool\",\n fields: [\n { type: \"text\", key: \"name\", label: \"Name\", required: true, placeholder: \"search_index\" },\n { type: \"text\", key: \"description\", label: \"When to use it\" },\n { type: \"json\", key: \"input_schema\", label: \"Input schema\",\n description: \"JSON Schema for the tool's arguments.\" },\n ],\n },\n { type: \"credential\", key: \"credential\", label: \"API credential\", credentialType: \"llm_credential\" },\n ],\n },\n {\n name: \"@particle-academy/llm_router\",\n // Every id this node has ever shipped under keeps resolving — MOIC's saved\n // flows carry the bare `llm_branch`.\n aliases: [\"llm_router\", \"llm_branch\", \"@fancy/llm_branch\", \"@fancy/llm_router\"],\n category: \"ai\",\n label: \"LLM Router\",\n description: \"Let a model choose which route the flow takes.\",\n icon: \"✧\",\n inputs: [{ id: \"in\" }],\n // Each declared route is a port. The executor returns `{ __port: id }`\n // (or `Port.only(id)` on the PHP runtime) to pick one.\n outputs: (config: any) => routePorts(config?.routes, config?.fallback),\n // A shuttle, not an engine: it carries the routes out to whatever LLM\n // client the host registered and carries the choice back. No provider SDK\n // reaches core, so this stays a builtin without adding a dependency.\n executor: llmRouterExecutor,\n configSchema: [\n { type: \"textarea\", key: \"system\", label: \"System prompt\", rows: 3,\n description: \"Optional framing for the routing decision.\" },\n { type: \"expression\", key: \"prompt\", label: \"What to route on\",\n example: \"{{ $json.message }}\", required: true },\n {\n type: \"repeater\",\n key: \"routes\",\n label: \"Routes\",\n description: \"The model picks exactly one. Descriptions are what it chooses between — make them distinct.\",\n titleKey: \"port\",\n addLabel: \"Add route\",\n minItems: 2,\n fields: [\n { type: \"text\", key: \"port\", label: \"Port\", required: true, placeholder: \"billing\" },\n { type: \"text\", key: \"description\", label: \"When to choose it\", required: true,\n placeholder: \"The user is asking about an invoice, refund, or payment.\" },\n ],\n default: [\n { port: \"a\", description: \"Describe when the model should pick this route.\" },\n { port: \"b\", description: \"Describe when the model should pick this route.\" },\n ],\n },\n { type: \"select\", key: \"provider\", label: \"Provider\", default: \"anthropic\",\n options: [\n { value: \"anthropic\", label: \"Anthropic\" },\n { value: \"openai\", label: \"OpenAI\" },\n { value: \"custom\", label: \"Custom\" },\n ] },\n { type: \"text\", key: \"model\", label: \"Model\", placeholder: \"claude-sonnet-4-5\" },\n { type: \"switch\", key: \"fallback\", label: \"Add a `fallback` port\", default: true,\n description: \"Where the flow goes if the model returns no usable route.\" },\n { type: \"credential\", key: \"credential\", label: \"API credential\", credentialType: \"llm_credential\" },\n ],\n },\n {\n name: \"@particle-academy/tool_use\",\n aliases: [\"tool_use\", \"@fancy/tool_use\"],\n category: \"ai\",\n label: \"Tool Use\",\n description: \"Hand control to a host-registered tool by name.\",\n icon: \"🛠\",\n configSchema: [\n { type: \"text\", key: \"tool\", label: \"Tool name\", placeholder: \"search_index\", required: true },\n { type: \"expression\", key: \"args\", label: \"Arguments\", example: \"{{ { query: $json.q } }}\" },\n ],\n },\n {\n name: \"@particle-academy/embed_search\",\n aliases: [\"embed_search\", \"@fancy/embed_search\"],\n category: \"ai\",\n label: \"Embed & Search\",\n description: \"Embed a query and search a vector store.\",\n icon: \"✺\",\n configSchema: [\n { type: \"expression\", key: \"query\", label: \"Query\", required: true, example: \"{{ $json.question }}\" },\n { type: \"number\", key: \"topK\", label: \"Top K\", default: 5, min: 1, max: 50 },\n { type: \"credential\", key: \"vectorStore\", label: \"Vector store\", credentialType: \"vector_store\" },\n ],\n },\n\n // ───────────── IO ─────────────\n {\n name: \"@particle-academy/api_request\",\n aliases: [\"api_request\", \"@fancy/api_request\"],\n category: \"io\",\n label: \"API Request\",\n description: \"HTTP request to any URL.\",\n icon: \"↔\",\n configSchema: [\n ...HTTP_METHODS,\n { type: \"text\", key: \"url\", label: \"URL\", placeholder: \"https://api.example.com/...\", required: true },\n { type: \"keyvalue\", key: \"headers\", label: \"Headers\",\n keyLabel: \"Header\", valueLabel: \"Value\",\n keyPlaceholder: \"content-type\", valuePlaceholder: \"application/json\",\n addLabel: \"Add header\",\n default: { \"content-type\": \"application/json\" } },\n { type: \"json\", key: \"body\", label: \"Body\" },\n { type: \"credential\", key: \"auth\", label: \"Auth\", credentialType: \"api_credential\" },\n ],\n },\n {\n name: \"@particle-academy/webhook_out\",\n aliases: [\"webhook_out\", \"@fancy/webhook_out\"],\n category: \"io\",\n label: \"Send Webhook\",\n description: \"POST a payload to a configured URL.\",\n icon: \"↗\",\n configSchema: [\n { type: \"text\", key: \"url\", label: \"URL\", required: true },\n { type: \"keyvalue\", key: \"headers\", label: \"Headers\",\n keyLabel: \"Header\", valueLabel: \"Value\", addLabel: \"Add header\" },\n { type: \"expression\", key: \"payload\", label: \"Payload\", required: true, example: \"{{ $json }}\" },\n ],\n },\n\n // ───────────── Human ─────────────\n {\n name: \"@particle-academy/human_approval\",\n aliases: [\"human_approval\", \"@fancy/human_approval\"],\n pausesForHuman: \"approval\",\n category: \"human\",\n label: \"Human Approval\",\n description: \"Pause until a human approves or denies.\",\n icon: \"✓\",\n inputs: [{ id: \"in\" }],\n outputs: [{ id: \"approved\", label: \"approved\" }, { id: \"denied\", label: \"denied\" }],\n configSchema: [\n { type: \"text\", key: \"title\", label: \"Approval title\", default: \"Approve action\" },\n { type: \"textarea\", key: \"description\", label: \"Description for approver\", rows: 3 },\n { type: \"credential\", key: \"channel\", label: \"Notify channel\", credentialType: \"notify_channel\" },\n ],\n },\n {\n name: \"@particle-academy/notify\",\n aliases: [\"notify\", \"@fancy/notify\"],\n category: \"human\",\n label: \"Notify\",\n description: \"Send a message via Slack / email / SMS / etc.\",\n icon: \"🔔\",\n configSchema: [\n { type: \"select\", key: \"channel\", label: \"Channel\", default: \"slack\",\n options: [\n { value: \"slack\", label: \"Slack\" }, { value: \"email\", label: \"Email\" },\n { value: \"sms\", label: \"SMS\" }, { value: \"discord\", label: \"Discord\" },\n ] },\n { type: \"text\", key: \"to\", label: \"To\", required: true },\n { type: \"expression\", key: \"message\", label: \"Message\", required: true, example: \"{{ $json.summary }}\" },\n ],\n },\n\n // ───────────── Output ─────────────\n {\n name: \"@particle-academy/output\",\n aliases: [\"output\", \"@fancy/output\"],\n category: \"output\",\n label: \"Output\",\n description: \"Terminal node — captures the workflow's result.\",\n icon: \"●\",\n inputs: [{ id: \"in\" }],\n outputs: [],\n },\n {\n name: \"@particle-academy/log\",\n aliases: [\"log\", \"@fancy/log\"],\n category: \"output\",\n label: \"Log\",\n description: \"Send to the run feed.\",\n icon: \"≡\",\n inputs: [{ id: \"in\" }],\n outputs: [],\n configSchema: [\n { type: \"select\", key: \"level\", label: \"Level\", default: \"info\",\n options: [{ value: \"info\", label: \"info\" }, { value: \"warn\", label: \"warn\" }, { value: \"error\", label: \"error\" }] },\n { type: \"expression\", key: \"message\", label: \"Message\", required: true, example: \"{{ $json }}\" },\n ],\n },\n];\n\n/** Register every built-in kind. Idempotent via the registry. */\nexport function registerBuiltinKinds(): void {\n for (const k of KINDS) registerNodeKind(k);\n}\n\n/** Exported list for hosts that want to selectively re-register. */\nexport const BUILTIN_KINDS: NodeKindDefinition[] = KINDS;\n","export type {\n ConfigField,\n TextConfigField,\n TextareaConfigField,\n NumberConfigField,\n SelectConfigField,\n SwitchConfigField,\n JsonConfigField,\n ExpressionConfigField,\n CredentialConfigField,\n RepeaterConfigField,\n RepeaterRowField,\n KeyValueConfigField,\n DocumentConfigField,\n NodeCategory,\n NodeKindDefinition,\n PortSpec,\n RenderBodyContext,\n} from \"./types\";\n\nexport { resolvePortSpec, resolveNodePorts, nodeConfig } from \"./ports\";\n\nexport {\n createConnectionValidator,\n defaultPortCompatibility,\n ANY_PORT_TYPE,\n type PortCompatibility,\n type ConnectionValidatorOptions,\n} from \"./connection\";\n\n/** Host capabilities — core declares the contract, the host supplies the impl. */\nexport {\n registerLlmClient,\n getLlmClient,\n registerWorkflowResolver,\n getWorkflowResolver,\n capabilityStatus,\n type LlmClient,\n type LlmRoute,\n type LlmRouteRequest,\n type LlmRouteChoice,\n type WorkflowResolver,\n type WorkflowResolution,\n type WorkflowResolutionFailure,\n type CapabilityId,\n isResolutionFailure,\n} from \"./capabilities\";\n\n/**\n * The human-pause contract — a run waiting for a person, not a failure.\n * `decodePause` is the one function a durable runner needs.\n */\nexport {\n pauseForHuman,\n encodePause,\n decodePause,\n isPause,\n PAUSE_PREFIX,\n LEGACY_PAUSE_PREFIXES,\n type PauseAwaiting,\n type PauseSignal,\n} from \"./pause\";\n\nexport { subflowExecutor, subflowPorts, subflowMode, DEFAULT_MAX_DEPTH, type SubflowMode } from \"./subflow\";\nexport { llmRouterExecutor, declaredRoutes, resolveFallbackPort } from \"./llm-router\";\n/** @deprecated Renamed to `llmRouterExecutor` — the id and label now match. */\nexport { llmRouterExecutor as llmBranchExecutor } from \"./llm-router\";\n\nexport {\n registerRichInputAdapter,\n getRichInputAdapter,\n isRichInputEnabled,\n onRichInputAdapterChanged,\n RichInputPreview,\n type RichInputAdapter,\n} from \"./rich-input\";\n\nexport {\n registerNodeKind,\n getNodeKind,\n resolveKindId,\n kindIds,\n listNodeKinds,\n onNodeKindsChanged,\n defaultConfigFor,\n validateConfig,\n categoryAccent,\n} from \"./registry\";\n\nexport { RegistryNode } from \"./RegistryNode\";\nexport { registerBuiltinKinds, BUILTIN_KINDS } from \"./builtin\";\n\nimport type { NodeTypes } from \"@xyflow/react\";\nimport { RegistryNode } from \"./RegistryNode\";\nimport { kindIds, listNodeKinds } from \"./registry\";\n\n/**\n * Build an xyflow `nodeTypes` map from the registry — every registered\n * kind gets `RegistryNode` as its renderer. Refresh manually via\n * `useNodeTypes()` (a hook that subscribes to registry changes).\n */\nexport function buildNodeTypes(): NodeTypes {\n const map: NodeTypes = {};\n for (const k of listNodeKinds()) {\n // Key on every id the kind answers to, not just the canonical one. xyflow\n // looks the renderer up by `node.type` BEFORE RegistryNode gets a chance to\n // resolve aliases, so a graph still carrying pre-namespace types would fall\n // through to the unknown-node placeholder.\n for (const id of kindIds(k)) map[id] = RegistryNode;\n }\n return map;\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { applyNodeChanges, applyEdgeChanges, addEdge } from './chunk-NF6NPY5N.js';
|
|
2
2
|
import { runFlow } from './chunk-L4AX73Q6.js';
|
|
3
|
-
import { useState, useRef, useCallback } from 'react';
|
|
3
|
+
import { useState, useRef, useCallback, useMemo } from 'react';
|
|
4
4
|
|
|
5
5
|
function useFlowRun({ maxFeed = 200 } = {}) {
|
|
6
6
|
const [statuses, setStatuses] = useState({});
|
|
@@ -105,10 +105,119 @@ function useFlowState(initial) {
|
|
|
105
105
|
const onConnect = useCallback((connection) => {
|
|
106
106
|
setEdges((es) => addEdge(connection, es));
|
|
107
107
|
}, []);
|
|
108
|
+
const setGraph = useCallback((graph) => {
|
|
109
|
+
setNodes(graph.nodes);
|
|
110
|
+
setEdges(graph.edges);
|
|
111
|
+
}, []);
|
|
108
112
|
const toGraph = useCallback(() => ({ nodes, edges }), [nodes, edges]);
|
|
109
|
-
return { nodes, edges, setNodes, setEdges, onNodesChange, onEdgesChange, onConnect, toGraph };
|
|
113
|
+
return { nodes, edges, setNodes, setEdges, setGraph, onNodesChange, onEdgesChange, onConnect, toGraph };
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// src/runtime/history.ts
|
|
117
|
+
function createHistory(limit = 100) {
|
|
118
|
+
let past = [];
|
|
119
|
+
let future = [];
|
|
120
|
+
return {
|
|
121
|
+
push(graph) {
|
|
122
|
+
past.push(graph);
|
|
123
|
+
if (past.length > limit) past.shift();
|
|
124
|
+
future = [];
|
|
125
|
+
},
|
|
126
|
+
undo(current) {
|
|
127
|
+
const prev = past.pop();
|
|
128
|
+
if (prev === void 0) return null;
|
|
129
|
+
future.push(current);
|
|
130
|
+
return prev;
|
|
131
|
+
},
|
|
132
|
+
redo(current) {
|
|
133
|
+
const next = future.pop();
|
|
134
|
+
if (next === void 0) return null;
|
|
135
|
+
past.push(current);
|
|
136
|
+
return next;
|
|
137
|
+
},
|
|
138
|
+
canUndo: () => past.length > 0,
|
|
139
|
+
canRedo: () => future.length > 0,
|
|
140
|
+
clear() {
|
|
141
|
+
past = [];
|
|
142
|
+
future = [];
|
|
143
|
+
},
|
|
144
|
+
size: () => ({ past: past.length, future: future.length })
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// src/runtime/use-flow-history.ts
|
|
149
|
+
function useFlowHistory(flow) {
|
|
150
|
+
const history = useRef(createHistory()).current;
|
|
151
|
+
const restoring = useRef(false);
|
|
152
|
+
const coalesced = useRef(false);
|
|
153
|
+
const [, bump] = useState(0);
|
|
154
|
+
const rerender = useCallback(() => bump((n) => n + 1), []);
|
|
155
|
+
const graphRef = useRef({ nodes: flow.nodes, edges: flow.edges });
|
|
156
|
+
graphRef.current = { nodes: flow.nodes, edges: flow.edges };
|
|
157
|
+
const capture = useCallback(() => {
|
|
158
|
+
if (restoring.current || coalesced.current) return;
|
|
159
|
+
coalesced.current = true;
|
|
160
|
+
queueMicrotask(() => {
|
|
161
|
+
coalesced.current = false;
|
|
162
|
+
});
|
|
163
|
+
history.push(graphRef.current);
|
|
164
|
+
rerender();
|
|
165
|
+
}, [history, rerender]);
|
|
166
|
+
const restore = useCallback(
|
|
167
|
+
(g) => {
|
|
168
|
+
if (!g) return;
|
|
169
|
+
restoring.current = true;
|
|
170
|
+
flow.setGraph(g);
|
|
171
|
+
queueMicrotask(() => {
|
|
172
|
+
restoring.current = false;
|
|
173
|
+
});
|
|
174
|
+
rerender();
|
|
175
|
+
},
|
|
176
|
+
[flow, rerender]
|
|
177
|
+
);
|
|
178
|
+
const undo = useCallback(() => restore(history.undo(graphRef.current)), [history, restore]);
|
|
179
|
+
const redo = useCallback(() => restore(history.redo(graphRef.current)), [history, restore]);
|
|
180
|
+
const wrapped = useMemo(
|
|
181
|
+
() => ({
|
|
182
|
+
...flow,
|
|
183
|
+
setNodes: (next) => {
|
|
184
|
+
capture();
|
|
185
|
+
flow.setNodes(next);
|
|
186
|
+
},
|
|
187
|
+
setEdges: (next) => {
|
|
188
|
+
capture();
|
|
189
|
+
flow.setEdges(next);
|
|
190
|
+
},
|
|
191
|
+
setGraph: (g) => {
|
|
192
|
+
capture();
|
|
193
|
+
flow.setGraph(g);
|
|
194
|
+
},
|
|
195
|
+
onNodesChange: (changes) => {
|
|
196
|
+
if (!restoring.current && changes.some((c) => c.type === "remove")) capture();
|
|
197
|
+
flow.onNodesChange(changes);
|
|
198
|
+
},
|
|
199
|
+
onEdgesChange: (changes) => {
|
|
200
|
+
if (!restoring.current && changes.some((c) => c.type === "remove")) capture();
|
|
201
|
+
flow.onEdgesChange(changes);
|
|
202
|
+
},
|
|
203
|
+
onConnect: (conn) => {
|
|
204
|
+
capture();
|
|
205
|
+
flow.onConnect(conn);
|
|
206
|
+
}
|
|
207
|
+
}),
|
|
208
|
+
[flow, capture]
|
|
209
|
+
);
|
|
210
|
+
return {
|
|
211
|
+
flow: wrapped,
|
|
212
|
+
undo,
|
|
213
|
+
redo,
|
|
214
|
+
canUndo: history.canUndo(),
|
|
215
|
+
canRedo: history.canRedo(),
|
|
216
|
+
capture,
|
|
217
|
+
onNodeDragStart: capture
|
|
218
|
+
};
|
|
110
219
|
}
|
|
111
220
|
|
|
112
|
-
export { applyStatusesToNodes, useFlowRun, useFlowState };
|
|
113
|
-
//# sourceMappingURL=chunk-
|
|
114
|
-
//# sourceMappingURL=chunk-
|
|
221
|
+
export { applyStatusesToNodes, createHistory, useFlowHistory, useFlowRun, useFlowState };
|
|
222
|
+
//# sourceMappingURL=chunk-PHX4SBOD.js.map
|
|
223
|
+
//# sourceMappingURL=chunk-PHX4SBOD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/runtime/use-flow-run.ts","../src/runtime/use-flow-state.ts","../src/runtime/history.ts","../src/runtime/use-flow-history.ts"],"names":["useState","useCallback","useRef"],"mappings":"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","file":"chunk-PHX4SBOD.js","sourcesContent":["import { useCallback, useRef, useState } from \"react\";\nimport { runFlow, type RunOptions, type RunResult } from \"./run-flow\";\nimport type {\n ExecutorRegistry,\n FlowGraph,\n NodeRunStatus,\n RunEvent,\n} from \"../types\";\n\nexport type FlowRunFeedEntry = {\n id: string;\n at: number;\n level: \"info\" | \"warn\" | \"error\" | \"status\";\n text: string;\n nodeId?: string;\n detail?: unknown;\n};\n\nexport type UseFlowRunReturn = {\n /** Status keyed by nodeId — drive the UI overlay from this. */\n statuses: Record<string, NodeRunStatus>;\n /** Per-node status text (e.g. error message). */\n statusText: Record<string, string | undefined>;\n /** Live event log (capped to last N). */\n feed: FlowRunFeedEntry[];\n /** Whether a run is currently in progress. */\n running: boolean;\n /** Last run result, or null. */\n lastResult: RunResult | null;\n /** Kick off a run with the provided graph + executors. */\n run: (graph: FlowGraph, executors: ExecutorRegistry, options?: RunOptions) => Promise<RunResult>;\n /** Cancel the current run (if any). */\n cancel: () => void;\n /** Reset all runtime state (statuses, feed, lastResult). */\n reset: () => void;\n};\n\nexport type UseFlowRunOptions = {\n /** Cap the in-memory feed to this many entries. Default 200. */\n maxFeed?: number;\n};\n\n/**\n * useFlowRun — drives `runFlow` + maintains observability state. Pair with\n * `applyStatusesToNodes` (below) before passing nodes to `<FlowCanvas>` so\n * the per-node status badge renders.\n */\nexport function useFlowRun({ maxFeed = 200 }: UseFlowRunOptions = {}): UseFlowRunReturn {\n const [statuses, setStatuses] = useState<Record<string, NodeRunStatus>>({});\n const [statusText, setStatusText] = useState<Record<string, string | undefined>>({});\n const [feed, setFeed] = useState<FlowRunFeedEntry[]>([]);\n const [running, setRunning] = useState(false);\n const [lastResult, setLastResult] = useState<RunResult | null>(null);\n const abortRef = useRef<AbortController | null>(null);\n\n const handleEvent = useCallback(\n (e: RunEvent) => {\n switch (e.type) {\n case \"node-status\":\n setStatuses((s) => ({ ...s, [e.nodeId]: e.status }));\n setStatusText((t) => ({ ...t, [e.nodeId]: e.text }));\n appendFeed({ level: \"status\", text: `${e.nodeId} → ${e.status}${e.text ? ` (${e.text})` : \"\"}`, nodeId: e.nodeId });\n break;\n case \"node-output\":\n appendFeed({ level: \"info\", text: `${e.nodeId}.${e.portId} = ${preview(e.value)}`, nodeId: e.nodeId, detail: e.value });\n break;\n case \"log\":\n appendFeed({ level: e.level, text: e.message, nodeId: e.nodeId, detail: e.detail });\n break;\n case \"run-start\":\n appendFeed({ level: \"info\", text: \"▶ run started\" });\n break;\n case \"run-end\":\n appendFeed({ level: e.ok ? \"info\" : \"error\", text: e.ok ? \"✓ run complete\" : \"✗ run failed\" });\n break;\n case \"run-error\":\n appendFeed({ level: \"error\", text: e.error });\n break;\n }\n function appendFeed(partial: Omit<FlowRunFeedEntry, \"id\" | \"at\">) {\n setFeed((f) => {\n const entry: FlowRunFeedEntry = { id: `${Date.now()}_${f.length}`, at: Date.now(), ...partial };\n const next = [...f, entry];\n return next.length > maxFeed ? next.slice(next.length - maxFeed) : next;\n });\n }\n },\n [maxFeed],\n );\n\n const run = useCallback(\n async (graph: FlowGraph, executors: ExecutorRegistry, options: RunOptions = {}) => {\n if (running) {\n return { ok: false, outputs: {}, error: \"another run is already in progress\" } satisfies RunResult;\n }\n const controller = new AbortController();\n abortRef.current = controller;\n // Reset previous statuses for the nodes we're about to run.\n const idleStatuses: Record<string, NodeRunStatus> = {};\n for (const n of graph.nodes) idleStatuses[n.id] = \"idle\";\n setStatuses(idleStatuses);\n setStatusText({});\n setRunning(true);\n try {\n const result = await runFlow(graph, executors, handleEvent, { ...options, signal: controller.signal });\n setLastResult(result);\n return result;\n } finally {\n setRunning(false);\n abortRef.current = null;\n }\n },\n [handleEvent, running],\n );\n\n const cancel = useCallback(() => abortRef.current?.abort(), []);\n\n const reset = useCallback(() => {\n setStatuses({});\n setStatusText({});\n setFeed([]);\n setLastResult(null);\n }, []);\n\n return { statuses, statusText, feed, running, lastResult, run, cancel, reset };\n}\n\n/** Merge runtime statuses into nodes for rendering. */\nexport function applyStatusesToNodes<TNode extends { id: string; data: any }>(\n nodes: TNode[],\n statuses: Record<string, NodeRunStatus>,\n statusText: Record<string, string | undefined>,\n): TNode[] {\n return nodes.map((n) => ({\n ...n,\n data: {\n ...n.data,\n status: statuses[n.id] ?? n.data?.status ?? \"idle\",\n statusText: statusText[n.id] ?? n.data?.statusText,\n },\n }));\n}\n\nfunction preview(v: unknown): string {\n try {\n const s = JSON.stringify(v);\n return s && s.length > 60 ? s.slice(0, 57) + \"…\" : (s ?? String(v));\n } catch {\n return String(v);\n }\n}\n","import { useCallback, useState } from \"react\";\nimport {\n addEdge,\n applyEdgeChanges,\n applyNodeChanges,\n type Connection,\n type Edge,\n type EdgeChange,\n type NodeChange,\n} from \"@xyflow/react\";\nimport type { FlowEdge, FlowGraph, FlowNode } from \"../types\";\n\nexport type UseFlowStateReturn = {\n nodes: FlowNode[];\n edges: FlowEdge[];\n setNodes: React.Dispatch<React.SetStateAction<FlowNode[]>>;\n setEdges: React.Dispatch<React.SetStateAction<FlowEdge[]>>;\n /**\n * Replace nodes AND edges atomically in a single commit. Use this for any op\n * that touches both (delete-with-edge-prune, undo/redo restore, setGraph):\n * calling `setNodes` then `setEdges` is NOT atomic in controlled mode (each\n * closes over a stale `value`), so the second write clobbers the first.\n */\n setGraph: (graph: FlowGraph) => void;\n onNodesChange: (changes: NodeChange[]) => void;\n onEdgesChange: (changes: EdgeChange[]) => void;\n onConnect: (connection: Connection) => void;\n /** Snapshot the current graph (suitable for serialization). */\n toGraph: () => FlowGraph;\n};\n\n/**\n * useFlowState — React Flow's standard controlled-state plumbing in one hook.\n * Spread into <FlowCanvas>.\n */\nexport function useFlowState(initial: FlowGraph): UseFlowStateReturn {\n const [nodes, setNodes] = useState<FlowNode[]>(initial.nodes);\n const [edges, setEdges] = useState<FlowEdge[]>(initial.edges);\n\n const onNodesChange = useCallback((changes: NodeChange[]) => {\n setNodes((ns) => applyNodeChanges(changes, ns) as FlowNode[]);\n }, []);\n const onEdgesChange = useCallback((changes: EdgeChange[]) => {\n setEdges((es) => applyEdgeChanges(changes, es));\n }, []);\n const onConnect = useCallback((connection: Connection) => {\n setEdges((es) => addEdge(connection, es) as Edge[]);\n }, []);\n\n const setGraph = useCallback((graph: FlowGraph) => {\n // Two useState writes in one event are batched, so this IS atomic here.\n setNodes(graph.nodes);\n setEdges(graph.edges);\n }, []);\n\n const toGraph = useCallback(() => ({ nodes, edges }), [nodes, edges]);\n\n return { nodes, edges, setNodes, setEdges, setGraph, onNodesChange, onEdgesChange, onConnect, toGraph };\n}\n","import type { FlowGraph } from \"../types\";\n\n/**\n * Undo/redo history — a pure, React-free snapshot controller. The editor pushes\n * a graph snapshot BEFORE each committing mutation; `undo`/`redo` swap snapshots\n * between the past/future stacks. Kept free of React so it can be unit-tested\n * and reused by any host (or a headless driver).\n *\n * Coalescing (collapsing a burst of setState calls from one logical op into a\n * single undo step) is the caller's job — see `useFlowHistory`.\n */\nexport type HistoryController = {\n /** Record `graph` as an undo point. Clears the redo stack (new branch). */\n push: (graph: FlowGraph) => void;\n /** Pop the last undo point; `current` is pushed onto the redo stack. */\n undo: (current: FlowGraph) => FlowGraph | null;\n /** Pop the last redo point; `current` is pushed back onto the undo stack. */\n redo: (current: FlowGraph) => FlowGraph | null;\n canUndo: () => boolean;\n canRedo: () => boolean;\n clear: () => void;\n /** Test/inspection helper — sizes of the two stacks. */\n size: () => { past: number; future: number };\n};\n\nexport function createHistory(limit = 100): HistoryController {\n let past: FlowGraph[] = [];\n let future: FlowGraph[] = [];\n\n return {\n push(graph) {\n past.push(graph);\n if (past.length > limit) past.shift();\n future = [];\n },\n undo(current) {\n const prev = past.pop();\n if (prev === undefined) return null;\n future.push(current);\n return prev;\n },\n redo(current) {\n const next = future.pop();\n if (next === undefined) return null;\n past.push(current);\n return next;\n },\n canUndo: () => past.length > 0,\n canRedo: () => future.length > 0,\n clear() {\n past = [];\n future = [];\n },\n size: () => ({ past: past.length, future: future.length }),\n };\n}\n","import { useCallback, useMemo, useRef, useState } from \"react\";\nimport type { EdgeChange, NodeChange } from \"@xyflow/react\";\nimport type { FlowGraph } from \"../types\";\nimport { createHistory } from \"./history\";\nimport type { UseFlowStateReturn } from \"./use-flow-state\";\n\nexport type UseFlowHistoryReturn = {\n /** The flow sink wrapped so committing mutations snapshot for undo first. */\n flow: UseFlowStateReturn;\n undo: () => void;\n redo: () => void;\n canUndo: boolean;\n canRedo: boolean;\n /** Snapshot the current graph as an undo point (before a programmatic edit). */\n capture: () => void;\n /** Wire to `<FlowCanvas onNodeDragStart>` — snapshots the pre-drag graph. */\n onNodeDragStart: () => void;\n};\n\n/**\n * useFlowHistory — the commit/undo pipeline. Wraps a flow sink (the uncontrolled\n * `useFlowState` hook OR the controlled adapter) so every *committing* mutation\n * records a snapshot first, giving undo/redo without the editor threading\n * history through each call site. This is the single interception point the\n * two-sink architecture otherwise lacks.\n *\n * Granularity: a burst of setState calls from one logical op (e.g. a\n * delete = setNodes+setEdges) is coalesced into ONE undo step; transient\n * interactive changes (drag-move, dimension-measure, selection) are NOT captured\n * — a drag is captured once at `onNodeDragStart` instead.\n */\nexport function useFlowHistory(flow: UseFlowStateReturn): UseFlowHistoryReturn {\n const history = useRef(createHistory()).current;\n const restoring = useRef(false);\n const coalesced = useRef(false);\n const [, bump] = useState(0);\n const rerender = useCallback(() => bump((n) => n + 1), []);\n\n // Latest graph via a ref, so capture never reads a stale snapshot.\n const graphRef = useRef<FlowGraph>({ nodes: flow.nodes, edges: flow.edges });\n graphRef.current = { nodes: flow.nodes, edges: flow.edges };\n\n const capture = useCallback(() => {\n if (restoring.current || coalesced.current) return;\n coalesced.current = true;\n queueMicrotask(() => {\n coalesced.current = false;\n });\n history.push(graphRef.current);\n rerender();\n }, [history, rerender]);\n\n const restore = useCallback(\n (g: FlowGraph | null) => {\n if (!g) return;\n restoring.current = true;\n flow.setGraph(g);\n queueMicrotask(() => {\n restoring.current = false;\n });\n rerender();\n },\n [flow, rerender],\n );\n\n const undo = useCallback(() => restore(history.undo(graphRef.current)), [history, restore]);\n const redo = useCallback(() => restore(history.redo(graphRef.current)), [history, restore]);\n\n const wrapped = useMemo<UseFlowStateReturn>(\n () => ({\n ...flow,\n setNodes: (next) => {\n capture();\n flow.setNodes(next);\n },\n setEdges: (next) => {\n capture();\n flow.setEdges(next);\n },\n setGraph: (g) => {\n capture();\n flow.setGraph(g);\n },\n onNodesChange: (changes: NodeChange[]) => {\n // Only structural removes commit; position/dimensions/select are transient.\n if (!restoring.current && changes.some((c) => c.type === \"remove\")) capture();\n flow.onNodesChange(changes);\n },\n onEdgesChange: (changes: EdgeChange[]) => {\n if (!restoring.current && changes.some((c) => c.type === \"remove\")) capture();\n flow.onEdgesChange(changes);\n },\n onConnect: (conn) => {\n capture();\n flow.onConnect(conn);\n },\n }),\n [flow, capture],\n );\n\n return {\n flow: wrapped,\n undo,\n redo,\n canUndo: history.canUndo(),\n canRedo: history.canRedo(),\n capture,\n onNodeDragStart: capture,\n };\n}\n"]}
|