@particle-academy/fancy-flow 0.47.0 → 0.47.1
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/{ConfigFieldRenderer-iMkZj0VK.d.ts → ConfigFieldRenderer-DrD2-Qml.d.ts} +1 -1
- package/dist/{ConfigFieldRenderer-Cyir8-B8.d.cts → ConfigFieldRenderer-NuDjtun1.d.cts} +1 -1
- package/dist/{chunk-QVFVL5LQ.js → chunk-7DTUZUTB.js} +3 -3
- package/dist/{chunk-QVFVL5LQ.js.map → chunk-7DTUZUTB.js.map} +1 -1
- package/dist/{chunk-DR3GWVDG.js → chunk-DRRZEAYB.js} +3 -3
- package/dist/{chunk-DR3GWVDG.js.map → chunk-DRRZEAYB.js.map} +1 -1
- package/dist/{chunk-ZKJJWBDJ.js → chunk-E6T3FZZP.js} +3 -3
- package/dist/{chunk-ZKJJWBDJ.js.map → chunk-E6T3FZZP.js.map} +1 -1
- package/dist/{chunk-ISXRQELT.js → chunk-KTGXZBUM.js} +3 -3
- package/dist/{chunk-ISXRQELT.js.map → chunk-KTGXZBUM.js.map} +1 -1
- package/dist/{chunk-NDEX655E.js → chunk-MJ3A3TAI.js} +2 -2
- package/dist/{chunk-NDEX655E.js.map → chunk-MJ3A3TAI.js.map} +1 -1
- package/dist/{chunk-Z2GRNYR2.js → chunk-UVP43XU2.js} +4 -4
- package/dist/{chunk-Z2GRNYR2.js.map → chunk-UVP43XU2.js.map} +1 -1
- package/dist/durable.cjs.map +1 -1
- package/dist/durable.js +1 -1
- package/dist/engine.cjs.map +1 -1
- package/dist/engine.d.cts +2 -2
- package/dist/engine.d.ts +2 -2
- package/dist/engine.js +3 -3
- package/dist/fields/react-fancy.d.cts +2 -2
- package/dist/fields/react-fancy.d.ts +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +11 -11
- package/dist/registry/index.d.cts +3 -3
- package/dist/registry/index.d.ts +3 -3
- package/dist/{registry-Bt55f63_.d.ts → registry-BnnifM-t.d.cts} +2 -2
- package/dist/{registry-CkcSwmfR.d.cts → registry-DpARG95T.d.ts} +2 -2
- package/dist/registry.cjs.map +1 -1
- package/dist/registry.js +2 -2
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.js +3 -3
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.js +2 -2
- package/dist/screens.cjs.map +1 -1
- package/dist/screens.js +4 -4
- package/dist/{types--S2Kzx7w.d.cts → types-BO8TgI2M.d.cts} +1 -1
- package/dist/{types-ChkCRonF.d.ts → types-DJAmfiJC.d.ts} +1 -1
- package/dist/ux.cjs.map +1 -1
- package/dist/ux.d.cts +1 -1
- package/dist/ux.d.ts +1 -1
- package/dist/ux.js +1 -1
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
import { F as FlowGraph } from './types-Jx1TwehV.js';
|
|
4
|
-
import { C as ConfigField } from './types-
|
|
4
|
+
import { C as ConfigField } from './types-DJAmfiJC.js';
|
|
5
5
|
|
|
6
6
|
/** What a host renderer is handed. */
|
|
7
7
|
type ConfigFieldRenderContext = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
import { F as FlowGraph } from './types-Jx1TwehV.cjs';
|
|
4
|
-
import { C as ConfigField } from './types
|
|
4
|
+
import { C as ConfigField } from './types-BO8TgI2M.cjs';
|
|
5
5
|
|
|
6
6
|
/** What a host renderer is handed. */
|
|
7
7
|
type ConfigFieldRenderContext = {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { runFlow } from './chunk-
|
|
1
|
+
import { runFlow } from './chunk-MJ3A3TAI.js';
|
|
2
2
|
|
|
3
3
|
// src/runtime/run-cohort.ts
|
|
4
4
|
async function runCohort(flows, executors, onEvent = () => {
|
|
@@ -46,5 +46,5 @@ function errorText(error) {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
export { runCohort };
|
|
49
|
-
//# sourceMappingURL=chunk-
|
|
50
|
-
//# sourceMappingURL=chunk-
|
|
49
|
+
//# sourceMappingURL=chunk-7DTUZUTB.js.map
|
|
50
|
+
//# sourceMappingURL=chunk-7DTUZUTB.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/runtime/run-cohort.ts"],"names":[],"mappings":";;;AAoFA,eAAsB,SAAA,CACpB,KAAA,EACA,SAAA,EACA,OAAA,GAAoD,MAAM;AAAC,CAAA,EAC3D,OAAA,GAAyB,EAAC,EACD;AACzB,EAAA,MAAM,EAAE,MAAA,GAAS,gBAAA,EAAkB,OAAO,MAAA,EAAQ,GAAG,YAAW,GAAI,OAAA;AAEpE,EAAA,IAAI,WAAW,UAAA,EAAY;AACzB,IAAA,OAAO,OAAA,CAAQ,GAAA;AAAA,MACb,KAAA,CAAM,GAAA,CAAI,OAAO,IAAA,EAAM,KAAA,MAAW;AAAA,QAChC,GAAI,MAAM,OAAA,CAAQ,IAAA,EAAM,SAAA,EAAW,CAAC,CAAA,KAAM,OAAA,CAAQ,CAAA,EAAG,KAAK,CAAA,EAAG,UAAU,CAAA;AAAA,QACvE;AAAA,OACF,CAAE;AAAA,KACJ;AAAA,EACF;AAEA,EAAA,MAAM,UAA0B,EAAC;AAEjC,EAAA,KAAA,MAAW,CAAC,KAAA,EAAO,IAAI,CAAA,IAAK,KAAA,CAAM,SAAQ,EAAG;AAC3C,IAAA,IAAI,MAAA,KAAW,oBAAoB,KAAA,EAAO;AACxC,MAAA,MAAM,GAAA,GAAM,MAAM,MAAA,GAAS,IAAA,EAAM,KAAK,CAAA,IAAK,sCAAA;AAC3C,MAAA,IAAI,MAAA;AAEJ,MAAA,IAAI;AACF,QAAA,MAAA,GAAS,MAAM,KAAA,CAAM,IAAA,EAAM,KAAK,CAAA;AAAA,MAClC,SAAS,KAAA,EAAO;AAGd,QAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,UACX,EAAA,EAAI,KAAA;AAAA,UACJ,SAAS,EAAC;AAAA,UACV,KAAA;AAAA,UACA,OAAA,EAAS,IAAA;AAAA,UACT,aAAA,EAAe,CAAA,8BAAA,EAAiC,SAAA,CAAU,KAAK,CAAC,CAAA;AAAA,SACjE,CAAA;AACD,QAAA;AAAA,MACF;AAEA,MAAA,IAAI,CAAC,MAAA,EAAQ;AACX,QAAA,OAAA,CAAQ,IAAA,CAAK,EAAE,EAAA,EAAI,KAAA,EAAO,OAAA,EAAS,EAAC,EAAG,KAAA,EAAO,OAAA,EAAS,IAAA,EAAM,aAAA,EAAe,GAAA,IAAO,CAAA;AACnF,QAAA;AAAA,MACF;AAAA,IACF;AAEA,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,GAAI,MAAM,OAAA,CAAQ,IAAA,EAAM,SAAA,EAAW,CAAC,CAAA,KAAM,OAAA,CAAQ,CAAA,EAAG,KAAK,CAAA,EAAG,UAAU,CAAA;AAAA,MACvE;AAAA,KACD,CAAA;AAAA,EACH;AAEA,EAAA,OAAO,OAAA;AACT;AAEA,SAAS,UAAU,KAAA,EAAwB;AACzC,EAAA,OAAO,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AAC9D","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../src/runtime/run-cohort.ts"],"names":[],"mappings":";;;AAoFA,eAAsB,SAAA,CACpB,KAAA,EACA,SAAA,EACA,OAAA,GAAoD,MAAM;AAAC,CAAA,EAC3D,OAAA,GAAyB,EAAC,EACD;AACzB,EAAA,MAAM,EAAE,MAAA,GAAS,gBAAA,EAAkB,OAAO,MAAA,EAAQ,GAAG,YAAW,GAAI,OAAA;AAEpE,EAAA,IAAI,WAAW,UAAA,EAAY;AACzB,IAAA,OAAO,OAAA,CAAQ,GAAA;AAAA,MACb,KAAA,CAAM,GAAA,CAAI,OAAO,IAAA,EAAM,KAAA,MAAW;AAAA,QAChC,GAAI,MAAM,OAAA,CAAQ,IAAA,EAAM,SAAA,EAAW,CAAC,CAAA,KAAM,OAAA,CAAQ,CAAA,EAAG,KAAK,CAAA,EAAG,UAAU,CAAA;AAAA,QACvE;AAAA,OACF,CAAE;AAAA,KACJ;AAAA,EACF;AAEA,EAAA,MAAM,UAA0B,EAAC;AAEjC,EAAA,KAAA,MAAW,CAAC,KAAA,EAAO,IAAI,CAAA,IAAK,KAAA,CAAM,SAAQ,EAAG;AAC3C,IAAA,IAAI,MAAA,KAAW,oBAAoB,KAAA,EAAO;AACxC,MAAA,MAAM,GAAA,GAAM,MAAM,MAAA,GAAS,IAAA,EAAM,KAAK,CAAA,IAAK,sCAAA;AAC3C,MAAA,IAAI,MAAA;AAEJ,MAAA,IAAI;AACF,QAAA,MAAA,GAAS,MAAM,KAAA,CAAM,IAAA,EAAM,KAAK,CAAA;AAAA,MAClC,SAAS,KAAA,EAAO;AAGd,QAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,UACX,EAAA,EAAI,KAAA;AAAA,UACJ,SAAS,EAAC;AAAA,UACV,KAAA;AAAA,UACA,OAAA,EAAS,IAAA;AAAA,UACT,aAAA,EAAe,CAAA,8BAAA,EAAiC,SAAA,CAAU,KAAK,CAAC,CAAA;AAAA,SACjE,CAAA;AACD,QAAA;AAAA,MACF;AAEA,MAAA,IAAI,CAAC,MAAA,EAAQ;AACX,QAAA,OAAA,CAAQ,IAAA,CAAK,EAAE,EAAA,EAAI,KAAA,EAAO,OAAA,EAAS,EAAC,EAAG,KAAA,EAAO,OAAA,EAAS,IAAA,EAAM,aAAA,EAAe,GAAA,IAAO,CAAA;AACnF,QAAA;AAAA,MACF;AAAA,IACF;AAEA,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,GAAI,MAAM,OAAA,CAAQ,IAAA,EAAM,SAAA,EAAW,CAAC,CAAA,KAAM,OAAA,CAAQ,CAAA,EAAG,KAAK,CAAA,EAAG,UAAU,CAAA;AAAA,MACvE;AAAA,KACD,CAAA;AAAA,EACH;AAEA,EAAA,OAAO,OAAA;AACT;AAEA,SAAS,UAAU,KAAA,EAAwB;AACzC,EAAA,OAAO,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AAC9D","file":"chunk-7DTUZUTB.js","sourcesContent":["import type { ExecutorRegistry, FlowGraph, RunEvent } from \"../types\";\nimport { runFlow, type RunOptions, type RunResult } from \"./run-flow\";\n\n/**\n * How the flows one trigger fired should treat each other.\n *\n * - `serial-guarded` (default) — run in the declared order, one at a time,\n * re-checking `guard` immediately before each. This is the safe default\n * because it is the only one that notices when an earlier flow invalidated\n * the state a later one was fired for.\n * - `serial` — ordered, one at a time, unguarded.\n * - `parallel` — all at once. Ordering is incidental and collisions are yours to\n * handle; correct for fan-outs that share no state, and only those.\n */\nexport type CohortPolicy = \"serial-guarded\" | \"serial\" | \"parallel\";\n\n/**\n * The precondition re-checked just before each flow starts.\n *\n * Return `false` (or throw) to skip that flow. The engine cannot know what\n * \"still valid\" means for your data, so it asks you — right before the run,\n * not at dispatch, because the whole hazard is what changed in between.\n */\nexport type CohortGuard = (\n flow: FlowGraph,\n index: number,\n) => boolean | Promise<boolean>;\n\nexport type CohortOptions = RunOptions & {\n policy?: CohortPolicy;\n guard?: CohortGuard;\n /** Why the guard said no — recorded on the skipped result. */\n reason?: (flow: FlowGraph, index: number) => string;\n};\n\nexport type CohortResult = RunResult & {\n index: number;\n /** True when the flow never ran because its guard did not pass. */\n skipped?: boolean;\n skippedReason?: string;\n};\n\n/**\n * runCohort — run every flow that one trigger event fired, as a group.\n *\n * ## Why this exists\n *\n * `runFlow` runs one graph. A host that fans a single webhook, schedule, or\n * record change out to several flows usually loops it — and a loop, or worse a\n * `Promise.all`, has no answer for the case that actually bites: one of those\n * flows deletes or mutates the record they were ALL fired for. The others then\n * run against state that is no longer there and resolve `ok: true`, having done\n * nothing. Nothing throws. Nothing is logged. That silent success is the failure\n * mode this function exists to remove.\n *\n * ## What it does\n *\n * Runs the flows in the order you declared, one at a time, and calls `guard`\n * immediately before each. A flow whose guard does not pass is returned with\n * `skipped: true` and a reason instead of being run — and the cohort carries on\n * to the next one.\n *\n * ```ts\n * const results = await runCohort([enrich, archive, notify], executors, undefined, {\n * initialInputs: { t: { deal } }, // snapshotted once, shared by all\n * guard: async () => Boolean(await findDeal(deal.id)),\n * reason: () => `deal ${deal.id} no longer exists`,\n * });\n * ```\n *\n * If `archive` deletes the deal, `notify` comes back skipped with that reason\n * rather than notifying about nothing.\n *\n * ## Failure does not cancel the cohort\n *\n * A flow that fails is reported and the next one still runs. \"The flow before me\n * threw\" is not an answer to \"is my input still there\" — the guard is, and it\n * gets asked either way.\n *\n * The Laravel twin (`FancyFlow::dispatchCohort()` in `fancy-flow-php`) is the\n * same contract across a queue, where each run is durable and hands on to its\n * successor when it settles. Same policies, same guard semantics, same\n * fail-closed rule.\n */\nexport async function runCohort(\n flows: FlowGraph[],\n executors: ExecutorRegistry,\n onEvent: (event: RunEvent, index: number) => void = () => {},\n options: CohortOptions = {},\n): Promise<CohortResult[]> {\n const { policy = \"serial-guarded\", guard, reason, ...runOptions } = options;\n\n if (policy === \"parallel\") {\n return Promise.all(\n flows.map(async (flow, index) => ({\n ...(await runFlow(flow, executors, (e) => onEvent(e, index), runOptions)),\n index,\n })),\n );\n }\n\n const results: CohortResult[] = [];\n\n for (const [index, flow] of flows.entries()) {\n if (policy === \"serial-guarded\" && guard) {\n const why = () => reason?.(flow, index) ?? \"trigger precondition no longer holds\";\n let passes: boolean;\n\n try {\n passes = await guard(flow, index);\n } catch (error) {\n // Fail CLOSED. A guard that cannot answer is not permission to proceed:\n // a skip is visible and re-runnable, a run over missing state is neither.\n results.push({\n ok: false,\n outputs: {},\n index,\n skipped: true,\n skippedReason: `guard could not be evaluated: ${errorText(error)}`,\n });\n continue;\n }\n\n if (!passes) {\n results.push({ ok: false, outputs: {}, index, skipped: true, skippedReason: why() });\n continue;\n }\n }\n\n results.push({\n ...(await runFlow(flow, executors, (e) => onEvent(e, index), runOptions)),\n index,\n });\n }\n\n return results;\n}\n\nfunction errorText(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getNodeKind, categoryAccent, resolveNodePorts, nodeConfig, NodeResizer, NodeToolbar, Handle, Position, listNodeKinds, kindIds } from './chunk-
|
|
1
|
+
import { getNodeKind, categoryAccent, resolveNodePorts, nodeConfig, NodeResizer, NodeToolbar, Handle, Position, listNodeKinds, kindIds } from './chunk-MJ3A3TAI.js';
|
|
2
2
|
import { memo, useMemo } from 'react';
|
|
3
3
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
4
|
|
|
@@ -192,5 +192,5 @@ function buildNodeTypes() {
|
|
|
192
192
|
}
|
|
193
193
|
|
|
194
194
|
export { ANY_PORT_TYPE, RegistryNode, buildNodeTypes, createConnectionValidator, defaultPortCompatibility };
|
|
195
|
-
//# sourceMappingURL=chunk-
|
|
196
|
-
//# sourceMappingURL=chunk-
|
|
195
|
+
//# sourceMappingURL=chunk-DRRZEAYB.js.map
|
|
196
|
+
//# sourceMappingURL=chunk-DRRZEAYB.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/registry/connection.ts","../src/registry/RegistryNode.tsx","../src/registry/index.ts"],"names":[],"mappings":"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","file":"chunk-DR3GWVDG.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 { memo, useMemo } from \"react\";\nimport { Handle, NodeResizer, NodeToolbar, 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 kind.resizable ? \"ff-node--resizable\" : \"\",\n ].filter(Boolean).join(\" \")}\n style={{ borderColor: props.selected ? accent : undefined }}\n >\n {kind.resizable && (\n <NodeResizer\n isVisible={props.selected ?? false}\n color={accent}\n {...(typeof kind.resizable === \"object\" ? kind.resizable : {})}\n />\n )}\n {kind.toolbar && (\n <NodeToolbar isVisible={props.selected ?? false}>\n {kind.toolbar({ nodeId: props.id, config: config as any, selected: props.selected ?? false })}\n </NodeToolbar>\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 {(data as any).output !== undefined && (\n <p className=\"ff-node__output\" title=\"Latest output\">→ {previewValue((data as any).output)}</p>\n )}\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 // A kind with no config schema has nothing to configure — don't nag with a\n // \"configure in the panel\" prompt (that's only for a kind that HAS fields but\n // none are filled in yet). Triggers, Output, etc. render as just their header.\n if (fields.length === 0) return null;\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","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 overrideNodeKind,\n clearNodeKindOverrides,\n type NodeKindPresentation,\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\";\nexport { ensureBuiltinKinds } from \"./registry\";\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 // A kind may bring its own full renderer (lanes/containers); otherwise the\n // default card. Key on every id the kind answers to, not just the canonical\n // one — xyflow looks the renderer up by `node.type` BEFORE RegistryNode gets\n // a chance to resolve aliases, so a graph carrying a pre-namespace type would\n // otherwise fall through to the unknown-node placeholder.\n const renderer = k.component ?? RegistryNode;\n for (const id of kindIds(k)) map[id] = renderer;\n }\n return map;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/registry/connection.ts","../src/registry/RegistryNode.tsx","../src/registry/index.ts"],"names":[],"mappings":"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","file":"chunk-DRRZEAYB.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 { memo, useMemo } from \"react\";\nimport { Handle, NodeResizer, NodeToolbar, 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 kind.resizable ? \"ff-node--resizable\" : \"\",\n ].filter(Boolean).join(\" \")}\n style={{ borderColor: props.selected ? accent : undefined }}\n >\n {kind.resizable && (\n <NodeResizer\n isVisible={props.selected ?? false}\n color={accent}\n {...(typeof kind.resizable === \"object\" ? kind.resizable : {})}\n />\n )}\n {kind.toolbar && (\n <NodeToolbar isVisible={props.selected ?? false}>\n {kind.toolbar({ nodeId: props.id, config: config as any, selected: props.selected ?? false })}\n </NodeToolbar>\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 {(data as any).output !== undefined && (\n <p className=\"ff-node__output\" title=\"Latest output\">→ {previewValue((data as any).output)}</p>\n )}\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 // A kind with no config schema has nothing to configure — don't nag with a\n // \"configure in the panel\" prompt (that's only for a kind that HAS fields but\n // none are filled in yet). Triggers, Output, etc. render as just their header.\n if (fields.length === 0) return null;\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","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 overrideNodeKind,\n clearNodeKindOverrides,\n type NodeKindPresentation,\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\";\nexport { ensureBuiltinKinds } from \"./registry\";\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 // A kind may bring its own full renderer (lanes/containers); otherwise the\n // default card. Key on every id the kind answers to, not just the canonical\n // one — xyflow looks the renderer up by `node.type` BEFORE RegistryNode gets\n // a chance to resolve aliases, so a graph carrying a pre-namespace type would\n // otherwise fall through to the unknown-node placeholder.\n const renderer = k.component ?? RegistryNode;\n for (const id of kindIds(k)) map[id] = renderer;\n }\n return map;\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { runFlow, getNodeKind, applyNodeChanges, applyEdgeChanges, addEdge } from './chunk-
|
|
1
|
+
import { runFlow, getNodeKind, applyNodeChanges, applyEdgeChanges, addEdge } from './chunk-MJ3A3TAI.js';
|
|
2
2
|
import { useState, useRef, useCallback, useMemo } from 'react';
|
|
3
3
|
|
|
4
4
|
function useFlowRun({ maxFeed = 200 } = {}) {
|
|
@@ -229,5 +229,5 @@ function useFlowHistory(flow) {
|
|
|
229
229
|
}
|
|
230
230
|
|
|
231
231
|
export { applyOutputsToNodes, applyStatusesToNodes, createHistory, useFlowHistory, useFlowRun, useFlowState };
|
|
232
|
-
//# sourceMappingURL=chunk-
|
|
233
|
-
//# sourceMappingURL=chunk-
|
|
232
|
+
//# sourceMappingURL=chunk-E6T3FZZP.js.map
|
|
233
|
+
//# sourceMappingURL=chunk-E6T3FZZP.js.map
|
|
@@ -1 +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-ZKJJWBDJ.js","sourcesContent":["import { useCallback, useRef, useState } from \"react\";\nimport { runFlow, type RunOptions, type RunResult } from \"./run-flow\";\nimport { getNodeKind } from \"../registry/registry\";\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 /** Latest computed output value per node (for reactive kinds). */\n outputs: Record<string, unknown>;\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 [outputs, setOutputs] = useState<Record<string, unknown>>({});\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 setOutputs((o) => ({ ...o, [e.nodeId]: e.value }));\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 setOutputs({});\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 setOutputs({});\n setFeed([]);\n setLastResult(null);\n }, []);\n\n return { statuses, statusText, outputs, feed, running, lastResult, run, cancel, reset };\n}\n\n/**\n * Write each reactive kind's latest run output into its `data.output`, so its\n * card can render the computed value live. Non-reactive kinds are returned\n * untouched. Pair with `applyStatusesToNodes` before rendering.\n */\nexport function applyOutputsToNodes<TNode extends { id: string; type?: string; data: any }>(\n nodes: TNode[],\n outputs: Record<string, unknown>,\n): TNode[] {\n return nodes.map((n) => {\n const kind = getNodeKind((n.data as any)?.kind ?? n.type ?? \"\");\n if (!kind?.reactive || !(n.id in outputs)) return n;\n return { ...n, data: { ...n.data, output: outputs[n.id] } };\n });\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"]}
|
|
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-E6T3FZZP.js","sourcesContent":["import { useCallback, useRef, useState } from \"react\";\nimport { runFlow, type RunOptions, type RunResult } from \"./run-flow\";\nimport { getNodeKind } from \"../registry/registry\";\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 /** Latest computed output value per node (for reactive kinds). */\n outputs: Record<string, unknown>;\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 [outputs, setOutputs] = useState<Record<string, unknown>>({});\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 setOutputs((o) => ({ ...o, [e.nodeId]: e.value }));\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 setOutputs({});\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 setOutputs({});\n setFeed([]);\n setLastResult(null);\n }, []);\n\n return { statuses, statusText, outputs, feed, running, lastResult, run, cancel, reset };\n}\n\n/**\n * Write each reactive kind's latest run output into its `data.output`, so its\n * card can render the computed value live. Non-reactive kinds are returned\n * untouched. Pair with `applyStatusesToNodes` before rendering.\n */\nexport function applyOutputsToNodes<TNode extends { id: string; type?: string; data: any }>(\n nodes: TNode[],\n outputs: Record<string, unknown>,\n): TNode[] {\n return nodes.map((n) => {\n const kind = getNodeKind((n.data as any)?.kind ?? n.type ?? \"\");\n if (!kind?.reactive || !(n.id in outputs)) return n;\n return { ...n, data: { ...n.data, output: outputs[n.id] } };\n });\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"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { resolveNodePorts, getNodeKind, defaultConfigFor, validateConfig } from './chunk-
|
|
1
|
+
import { resolveNodePorts, getNodeKind, defaultConfigFor, validateConfig } from './chunk-MJ3A3TAI.js';
|
|
2
2
|
|
|
3
3
|
// src/schema/workflow-schema.ts
|
|
4
4
|
var WORKFLOW_SCHEMA_VERSION = 1;
|
|
@@ -133,5 +133,5 @@ function workflowToBlob(schema) {
|
|
|
133
133
|
}
|
|
134
134
|
|
|
135
135
|
export { WORKFLOW_SCHEMA_URL, WORKFLOW_SCHEMA_VERSION, exportWorkflow, importWorkflow, migrateSchema, workflowToBlob };
|
|
136
|
-
//# sourceMappingURL=chunk-
|
|
137
|
-
//# sourceMappingURL=chunk-
|
|
136
|
+
//# sourceMappingURL=chunk-KTGXZBUM.js.map
|
|
137
|
+
//# sourceMappingURL=chunk-KTGXZBUM.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/schema/workflow-schema.ts"],"names":[],"mappings":"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","file":"chunk-ISXRQELT.js","sourcesContent":["import type { FlowEdge, FlowGraph, FlowNode, PortDescriptor } from \"../types\";\nimport { defaultConfigFor, getNodeKind, validateConfig } from \"../registry/registry\";\nimport { resolveNodePorts } from \"../registry/ports\";\n\n/** Schema version. Bump on breaking shape changes; add migrations as needed. */\nexport const WORKFLOW_SCHEMA_VERSION = 1 as const;\nexport const WORKFLOW_SCHEMA_URL = \"https://particle.academy/schemas/workflow/v1.json\";\n\nexport type WorkflowSchema = {\n $schema: typeof WORKFLOW_SCHEMA_URL;\n version: typeof WORKFLOW_SCHEMA_VERSION;\n metadata?: WorkflowMetadata;\n graph: {\n nodes: WorkflowSchemaNode[];\n edges: WorkflowSchemaEdge[];\n };\n view?: {\n viewport?: { x: number; y: number; zoom: number };\n };\n};\n\nexport type WorkflowMetadata = {\n id?: string;\n name?: string;\n description?: string;\n createdAt?: number;\n updatedAt?: number;\n author?: string;\n tags?: string[];\n};\n\nexport type WorkflowSchemaNode = {\n id: string;\n /** Registry kind name (e.g. \"memory_store\"). */\n kind: string;\n position: { x: number; y: number };\n label?: string;\n description?: string;\n config?: Record<string, unknown>;\n /**\n * Resolved ports, written on export.\n *\n * A kind may derive its ports from config (`switch_case` cases,\n * `llm_branch` routes), and that derivation is a JavaScript function — a\n * runtime in another language cannot execute it. Without the resolved ports\n * in the document, the PHP twin sees no declared outputs and falls back to a\n * single `out`, so every branch edge in an exported flow silently stops\n * firing. Serializing them keeps the schema self-describing and preserves\n * the cross-runtime guarantee: same JSON in, same routing out.\n *\n * Optional and additive — a hand-written schema may omit them, and each\n * runtime then falls back to its own kind registry.\n */\n inputs?: PortDescriptor[];\n outputs?: PortDescriptor[];\n /**\n * Visual layout — additive + optional. `parentId`/`extent` carry node grouping\n * (swimlanes / containers); `width`/`height` carry an explicit (resized) size;\n * `style` carries inline presentation. A runtime that only walks edges/ports\n * (e.g. the PHP twin) ignores all of these — they exist purely for the canvas,\n * so an older reader that doesn't know them simply drops them.\n */\n parentId?: string;\n extent?: \"parent\" | [[number, number], [number, number]];\n width?: number;\n height?: number;\n style?: Record<string, unknown>;\n};\n\nexport type WorkflowSchemaEdge = {\n id: string;\n source: string;\n target: string;\n sourceHandle?: string;\n targetHandle?: string;\n label?: string;\n};\n\nexport type ImportIssue = {\n level: \"error\" | \"warning\";\n nodeId?: string;\n edgeId?: string;\n message: string;\n};\n\nexport type ImportResult = {\n graph: FlowGraph;\n issues: ImportIssue[];\n /** True when the import produced a usable graph (errors may have been\n * rewritten to warnings via `lenient: true`). */\n ok: boolean;\n};\n\n/** Snapshot the in-memory graph as a portable WorkflowSchema. */\nexport function exportWorkflow(\n graph: FlowGraph,\n metadata?: WorkflowMetadata,\n view?: WorkflowSchema[\"view\"],\n): WorkflowSchema {\n return {\n $schema: WORKFLOW_SCHEMA_URL,\n version: WORKFLOW_SCHEMA_VERSION,\n metadata: metadata ? { ...metadata, updatedAt: Date.now() } : undefined,\n graph: {\n nodes: graph.nodes.map(toSchemaNode),\n edges: graph.edges.map(toSchemaEdge),\n },\n view,\n };\n}\n\nfunction toSchemaNode(n: FlowNode): WorkflowSchemaNode {\n const data: any = n.data ?? {};\n const kindName = data.kind ?? n.type ?? \"custom\";\n // Resolve through the same helper the canvas and runtime use, so a\n // config-driven kind writes its ACTUAL ports into the document instead of\n // leaving another language's runtime to guess at them.\n const ports = resolveNodePorts(n, getNodeKind(kindName) ?? undefined);\n const node = n as any;\n return {\n id: n.id,\n kind: kindName,\n position: { x: n.position.x, y: n.position.y },\n label: data.label,\n description: data.description,\n config: data.config,\n inputs: ports.inputs,\n outputs: ports.outputs,\n // Visual layout — only when explicitly set (never persist auto-`measured`\n // dimensions, which are derived, not authored).\n ...(node.parentId ? { parentId: node.parentId } : {}),\n ...(node.extent ? { extent: node.extent } : {}),\n ...(typeof node.width === \"number\" ? { width: node.width } : {}),\n ...(typeof node.height === \"number\" ? { height: node.height } : {}),\n ...(node.style ? { style: node.style } : {}),\n };\n}\n\nfunction toSchemaEdge(e: FlowEdge): WorkflowSchemaEdge {\n return {\n id: e.id,\n source: e.source,\n target: e.target,\n sourceHandle: e.sourceHandle ?? undefined,\n targetHandle: e.targetHandle ?? undefined,\n label: typeof e.label === \"string\" ? e.label : undefined,\n };\n}\n\nexport type ImportOptions = {\n /** When true, unknown kinds become warnings + a \"custom\" placeholder\n * instead of errors. Default false. */\n lenient?: boolean;\n};\n\n/**\n * Migrate a raw schema object up to the current version. Additive changes need\n * no migration (an older document simply lacks the newer optional fields); this\n * is the seam for a future BREAKING bump — add `case N → N+1` steps here and\n * `importWorkflow` runs them before validating the version.\n */\nexport function migrateSchema(schema: unknown): unknown {\n // v1 is current — nothing to migrate yet.\n return schema;\n}\n\n/**\n * Hydrate a schema into runtime FlowGraph + validate kinds/configs against\n * the registry. Reports issues for unknown kinds, missing required config,\n * and dangling edges.\n */\nexport function importWorkflow(schema: unknown, options: ImportOptions = {}): ImportResult {\n const issues: ImportIssue[] = [];\n const lenient = options.lenient === true;\n schema = migrateSchema(schema);\n\n if (!schema || typeof schema !== \"object\") {\n return { ok: false, graph: { nodes: [], edges: [] }, issues: [{ level: \"error\", message: \"Schema is not an object.\" }] };\n }\n const s = schema as Partial<WorkflowSchema>;\n if (s.version !== WORKFLOW_SCHEMA_VERSION) {\n issues.push({\n level: lenient ? \"warning\" : \"error\",\n message: `Unsupported workflow schema version: ${s.version} (expected ${WORKFLOW_SCHEMA_VERSION})`,\n });\n if (!lenient) return { ok: false, graph: { nodes: [], edges: [] }, issues };\n }\n\n const rawNodes = s.graph?.nodes ?? [];\n const rawEdges = s.graph?.edges ?? [];\n\n const nodes: FlowNode[] = rawNodes.map((n) => {\n const kind = getNodeKind(n.kind);\n if (!kind) {\n issues.push({\n level: lenient ? \"warning\" : \"error\",\n nodeId: n.id,\n message: `Unknown kind \"${n.kind}\" — register it before importing.`,\n });\n }\n const config = n.config ?? (kind ? defaultConfigFor(kind) : {});\n if (kind) {\n for (const iss of validateConfig(kind, config)) {\n issues.push({ level: \"warning\", nodeId: n.id, message: `${iss.key}: ${iss.message}` });\n }\n }\n // Canonicalise on the way in: a document may carry a pre-namespace id, and\n // rewriting it here means the graph converges on the canonical id the next\n // time it is saved, rather than carrying the ambiguous name forever.\n const kindId = kind?.name ?? n.kind;\n return {\n id: n.id,\n type: kindId,\n position: { x: n.position?.x ?? 0, y: n.position?.y ?? 0 },\n // Rehydrate visual layout onto the node's top level (where xyflow reads it).\n ...(n.parentId ? { parentId: n.parentId } : {}),\n ...(n.extent ? { extent: n.extent } : {}),\n ...(typeof n.width === \"number\" ? { width: n.width } : {}),\n ...(typeof n.height === \"number\" ? { height: n.height } : {}),\n ...(n.style ? { style: n.style } : {}),\n data: {\n kind: kindId,\n label: n.label ?? kind?.label ?? n.kind,\n description: n.description,\n config,\n // Carry serialized ports back onto the node so a round-trip is stable\n // and an unknown kind still routes the way the document described.\n ...(n.inputs ? { inputs: n.inputs } : {}),\n ...(n.outputs ? { outputs: n.outputs } : {}),\n } as any,\n };\n });\n\n const nodeIds = new Set(nodes.map((n) => n.id));\n const edges: FlowEdge[] = rawEdges\n .map((e) => {\n if (!nodeIds.has(e.source)) {\n issues.push({ level: \"warning\", edgeId: e.id, message: `Edge source \"${e.source}\" not found.` });\n return null;\n }\n if (!nodeIds.has(e.target)) {\n issues.push({ level: \"warning\", edgeId: e.id, message: `Edge target \"${e.target}\" not found.` });\n return null;\n }\n return {\n id: e.id,\n source: e.source,\n target: e.target,\n sourceHandle: e.sourceHandle,\n targetHandle: e.targetHandle,\n label: e.label,\n } as FlowEdge;\n })\n .filter((e): e is FlowEdge => e !== null);\n\n const ok = issues.every((i) => i.level !== \"error\");\n return { ok, graph: { nodes, edges }, issues };\n}\n\n/** Convenience: serialize a schema as a downloadable JSON Blob. */\nexport function workflowToBlob(schema: WorkflowSchema): Blob {\n return new Blob([JSON.stringify(schema, null, 2)], { type: \"application/json\" });\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/schema/workflow-schema.ts"],"names":[],"mappings":"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","file":"chunk-KTGXZBUM.js","sourcesContent":["import type { FlowEdge, FlowGraph, FlowNode, PortDescriptor } from \"../types\";\nimport { defaultConfigFor, getNodeKind, validateConfig } from \"../registry/registry\";\nimport { resolveNodePorts } from \"../registry/ports\";\n\n/** Schema version. Bump on breaking shape changes; add migrations as needed. */\nexport const WORKFLOW_SCHEMA_VERSION = 1 as const;\nexport const WORKFLOW_SCHEMA_URL = \"https://particle.academy/schemas/workflow/v1.json\";\n\nexport type WorkflowSchema = {\n $schema: typeof WORKFLOW_SCHEMA_URL;\n version: typeof WORKFLOW_SCHEMA_VERSION;\n metadata?: WorkflowMetadata;\n graph: {\n nodes: WorkflowSchemaNode[];\n edges: WorkflowSchemaEdge[];\n };\n view?: {\n viewport?: { x: number; y: number; zoom: number };\n };\n};\n\nexport type WorkflowMetadata = {\n id?: string;\n name?: string;\n description?: string;\n createdAt?: number;\n updatedAt?: number;\n author?: string;\n tags?: string[];\n};\n\nexport type WorkflowSchemaNode = {\n id: string;\n /** Registry kind name (e.g. \"memory_store\"). */\n kind: string;\n position: { x: number; y: number };\n label?: string;\n description?: string;\n config?: Record<string, unknown>;\n /**\n * Resolved ports, written on export.\n *\n * A kind may derive its ports from config (`switch_case` cases,\n * `llm_branch` routes), and that derivation is a JavaScript function — a\n * runtime in another language cannot execute it. Without the resolved ports\n * in the document, the PHP twin sees no declared outputs and falls back to a\n * single `out`, so every branch edge in an exported flow silently stops\n * firing. Serializing them keeps the schema self-describing and preserves\n * the cross-runtime guarantee: same JSON in, same routing out.\n *\n * Optional and additive — a hand-written schema may omit them, and each\n * runtime then falls back to its own kind registry.\n */\n inputs?: PortDescriptor[];\n outputs?: PortDescriptor[];\n /**\n * Visual layout — additive + optional. `parentId`/`extent` carry node grouping\n * (swimlanes / containers); `width`/`height` carry an explicit (resized) size;\n * `style` carries inline presentation. A runtime that only walks edges/ports\n * (e.g. the PHP twin) ignores all of these — they exist purely for the canvas,\n * so an older reader that doesn't know them simply drops them.\n */\n parentId?: string;\n extent?: \"parent\" | [[number, number], [number, number]];\n width?: number;\n height?: number;\n style?: Record<string, unknown>;\n};\n\nexport type WorkflowSchemaEdge = {\n id: string;\n source: string;\n target: string;\n sourceHandle?: string;\n targetHandle?: string;\n label?: string;\n};\n\nexport type ImportIssue = {\n level: \"error\" | \"warning\";\n nodeId?: string;\n edgeId?: string;\n message: string;\n};\n\nexport type ImportResult = {\n graph: FlowGraph;\n issues: ImportIssue[];\n /** True when the import produced a usable graph (errors may have been\n * rewritten to warnings via `lenient: true`). */\n ok: boolean;\n};\n\n/** Snapshot the in-memory graph as a portable WorkflowSchema. */\nexport function exportWorkflow(\n graph: FlowGraph,\n metadata?: WorkflowMetadata,\n view?: WorkflowSchema[\"view\"],\n): WorkflowSchema {\n return {\n $schema: WORKFLOW_SCHEMA_URL,\n version: WORKFLOW_SCHEMA_VERSION,\n metadata: metadata ? { ...metadata, updatedAt: Date.now() } : undefined,\n graph: {\n nodes: graph.nodes.map(toSchemaNode),\n edges: graph.edges.map(toSchemaEdge),\n },\n view,\n };\n}\n\nfunction toSchemaNode(n: FlowNode): WorkflowSchemaNode {\n const data: any = n.data ?? {};\n const kindName = data.kind ?? n.type ?? \"custom\";\n // Resolve through the same helper the canvas and runtime use, so a\n // config-driven kind writes its ACTUAL ports into the document instead of\n // leaving another language's runtime to guess at them.\n const ports = resolveNodePorts(n, getNodeKind(kindName) ?? undefined);\n const node = n as any;\n return {\n id: n.id,\n kind: kindName,\n position: { x: n.position.x, y: n.position.y },\n label: data.label,\n description: data.description,\n config: data.config,\n inputs: ports.inputs,\n outputs: ports.outputs,\n // Visual layout — only when explicitly set (never persist auto-`measured`\n // dimensions, which are derived, not authored).\n ...(node.parentId ? { parentId: node.parentId } : {}),\n ...(node.extent ? { extent: node.extent } : {}),\n ...(typeof node.width === \"number\" ? { width: node.width } : {}),\n ...(typeof node.height === \"number\" ? { height: node.height } : {}),\n ...(node.style ? { style: node.style } : {}),\n };\n}\n\nfunction toSchemaEdge(e: FlowEdge): WorkflowSchemaEdge {\n return {\n id: e.id,\n source: e.source,\n target: e.target,\n sourceHandle: e.sourceHandle ?? undefined,\n targetHandle: e.targetHandle ?? undefined,\n label: typeof e.label === \"string\" ? e.label : undefined,\n };\n}\n\nexport type ImportOptions = {\n /** When true, unknown kinds become warnings + a \"custom\" placeholder\n * instead of errors. Default false. */\n lenient?: boolean;\n};\n\n/**\n * Migrate a raw schema object up to the current version. Additive changes need\n * no migration (an older document simply lacks the newer optional fields); this\n * is the seam for a future BREAKING bump — add `case N → N+1` steps here and\n * `importWorkflow` runs them before validating the version.\n */\nexport function migrateSchema(schema: unknown): unknown {\n // v1 is current — nothing to migrate yet.\n return schema;\n}\n\n/**\n * Hydrate a schema into runtime FlowGraph + validate kinds/configs against\n * the registry. Reports issues for unknown kinds, missing required config,\n * and dangling edges.\n */\nexport function importWorkflow(schema: unknown, options: ImportOptions = {}): ImportResult {\n const issues: ImportIssue[] = [];\n const lenient = options.lenient === true;\n schema = migrateSchema(schema);\n\n if (!schema || typeof schema !== \"object\") {\n return { ok: false, graph: { nodes: [], edges: [] }, issues: [{ level: \"error\", message: \"Schema is not an object.\" }] };\n }\n const s = schema as Partial<WorkflowSchema>;\n if (s.version !== WORKFLOW_SCHEMA_VERSION) {\n issues.push({\n level: lenient ? \"warning\" : \"error\",\n message: `Unsupported workflow schema version: ${s.version} (expected ${WORKFLOW_SCHEMA_VERSION})`,\n });\n if (!lenient) return { ok: false, graph: { nodes: [], edges: [] }, issues };\n }\n\n const rawNodes = s.graph?.nodes ?? [];\n const rawEdges = s.graph?.edges ?? [];\n\n const nodes: FlowNode[] = rawNodes.map((n) => {\n const kind = getNodeKind(n.kind);\n if (!kind) {\n issues.push({\n level: lenient ? \"warning\" : \"error\",\n nodeId: n.id,\n message: `Unknown kind \"${n.kind}\" — register it before importing.`,\n });\n }\n const config = n.config ?? (kind ? defaultConfigFor(kind) : {});\n if (kind) {\n for (const iss of validateConfig(kind, config)) {\n issues.push({ level: \"warning\", nodeId: n.id, message: `${iss.key}: ${iss.message}` });\n }\n }\n // Canonicalise on the way in: a document may carry a pre-namespace id, and\n // rewriting it here means the graph converges on the canonical id the next\n // time it is saved, rather than carrying the ambiguous name forever.\n const kindId = kind?.name ?? n.kind;\n return {\n id: n.id,\n type: kindId,\n position: { x: n.position?.x ?? 0, y: n.position?.y ?? 0 },\n // Rehydrate visual layout onto the node's top level (where xyflow reads it).\n ...(n.parentId ? { parentId: n.parentId } : {}),\n ...(n.extent ? { extent: n.extent } : {}),\n ...(typeof n.width === \"number\" ? { width: n.width } : {}),\n ...(typeof n.height === \"number\" ? { height: n.height } : {}),\n ...(n.style ? { style: n.style } : {}),\n data: {\n kind: kindId,\n label: n.label ?? kind?.label ?? n.kind,\n description: n.description,\n config,\n // Carry serialized ports back onto the node so a round-trip is stable\n // and an unknown kind still routes the way the document described.\n ...(n.inputs ? { inputs: n.inputs } : {}),\n ...(n.outputs ? { outputs: n.outputs } : {}),\n } as any,\n };\n });\n\n const nodeIds = new Set(nodes.map((n) => n.id));\n const edges: FlowEdge[] = rawEdges\n .map((e) => {\n if (!nodeIds.has(e.source)) {\n issues.push({ level: \"warning\", edgeId: e.id, message: `Edge source \"${e.source}\" not found.` });\n return null;\n }\n if (!nodeIds.has(e.target)) {\n issues.push({ level: \"warning\", edgeId: e.id, message: `Edge target \"${e.target}\" not found.` });\n return null;\n }\n return {\n id: e.id,\n source: e.source,\n target: e.target,\n sourceHandle: e.sourceHandle,\n targetHandle: e.targetHandle,\n label: e.label,\n } as FlowEdge;\n })\n .filter((e): e is FlowEdge => e !== null);\n\n const ok = issues.every((i) => i.level !== \"error\");\n return { ok, graph: { nodes, edges }, issues };\n}\n\n/** Convenience: serialize a schema as a downloadable JSON Blob. */\nexport function workflowToBlob(schema: WorkflowSchema): Blob {\n return new Blob([JSON.stringify(schema, null, 2)], { type: \"application/json\" });\n}\n"]}
|
|
@@ -10604,5 +10604,5 @@ function LaneNodeInner(props) {
|
|
|
10604
10604
|
var LaneNode = memo(LaneNodeInner);
|
|
10605
10605
|
|
|
10606
10606
|
export { BUILTIN_KINDS, Background, BackgroundVariant, Controls, DEFAULT_MAX_DEPTH, FlowEditorProvider, Handle, LaneNode, MiniMap, NodeResizer, NodeToolbar, NoteNode, Position, ReactFlowProvider, RunIdentity, ViewportPortal, addEdge2 as addEdge, applyEdgeChanges, applyNodeChanges, categoryAccent, clearNodeKindOverrides, declaredRoutes, defaultConfigFor, ensureBuiltinKinds, escapeSegment, getNodeKind, index, kindIds, listNodeKinds, llmRouterExecutor, nodeConfig, onNodeKindsChanged, overrideNodeKind, reconnectEdge2 as reconnectEdge, registerBuiltinKinds, registerNodeKind, resolveFallbackPort, resolveKindId, resolveNodePorts, resolvePortSpec, runFlow, subflowExecutor, subflowMode, subflowPorts, useFlowEditor, useFlowEditorOptional, useReactFlow, validateConfig };
|
|
10607
|
-
//# sourceMappingURL=chunk-
|
|
10608
|
-
//# sourceMappingURL=chunk-
|
|
10607
|
+
//# sourceMappingURL=chunk-MJ3A3TAI.js.map
|
|
10608
|
+
//# sourceMappingURL=chunk-MJ3A3TAI.js.map
|