@particle-academy/fancy-flow 0.20.0 → 0.22.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.
Files changed (60) hide show
  1. package/dist/{capabilities-DUhAc-EJ.d.ts → capabilities-85Mjn4uW.d.ts} +1 -1
  2. package/dist/{capabilities-ChE3Xi8R.d.cts → capabilities-exVeADXz.d.cts} +1 -1
  3. package/dist/{chunk-L4AX73Q6.js → chunk-KDHLKBL2.js} +11 -5
  4. package/dist/chunk-KDHLKBL2.js.map +1 -0
  5. package/dist/{chunk-KI4RI2N3.js → chunk-O7F6SGV4.js} +4 -4
  6. package/dist/{chunk-KI4RI2N3.js.map → chunk-O7F6SGV4.js.map} +1 -1
  7. package/dist/{chunk-D6W5FMCT.js → chunk-OHVSEHDC.js} +23 -5
  8. package/dist/chunk-OHVSEHDC.js.map +1 -0
  9. package/dist/{chunk-U5F22BHV.js → chunk-YXRLIV7A.js} +4 -2
  10. package/dist/chunk-YXRLIV7A.js.map +1 -0
  11. package/dist/{chunk-AW2QUEL2.js → chunk-YZTBRXBZ.js} +66 -8
  12. package/dist/chunk-YZTBRXBZ.js.map +1 -0
  13. package/dist/{chunk-XETAGLH6.js → chunk-ZB4HHQMR.js} +130 -32
  14. package/dist/chunk-ZB4HHQMR.js.map +1 -0
  15. package/dist/engine.cjs +8 -2
  16. package/dist/engine.cjs.map +1 -1
  17. package/dist/engine.d.cts +3 -3
  18. package/dist/engine.d.ts +3 -3
  19. package/dist/engine.js +3 -3
  20. package/dist/index.cjs +3553 -3278
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.d.cts +25 -8
  23. package/dist/index.d.ts +25 -8
  24. package/dist/index.js +200 -107
  25. package/dist/index.js.map +1 -1
  26. package/dist/llm/vercel-ai.d.cts +2 -2
  27. package/dist/llm/vercel-ai.d.ts +2 -2
  28. package/dist/registry/index.d.cts +5 -5
  29. package/dist/registry/index.d.ts +5 -5
  30. package/dist/registry.cjs +197 -33
  31. package/dist/registry.cjs.map +1 -1
  32. package/dist/registry.js +4 -4
  33. package/dist/{run-flow-ChBi6q-W.d.ts → run-flow-9U-gaYVF.d.ts} +1 -1
  34. package/dist/{run-flow-VKm57Hcj.d.cts → run-flow-AXzOR-Wq.d.cts} +1 -1
  35. package/dist/runtime/index.d.cts +3 -3
  36. package/dist/runtime/index.d.ts +3 -3
  37. package/dist/runtime.cjs +8 -2
  38. package/dist/runtime.cjs.map +1 -1
  39. package/dist/runtime.js +4 -4
  40. package/dist/schema/index.d.cts +21 -2
  41. package/dist/schema/index.d.ts +21 -2
  42. package/dist/schema.cjs +20 -1
  43. package/dist/schema.cjs.map +1 -1
  44. package/dist/schema.js +2 -2
  45. package/dist/styles.css +61 -0
  46. package/dist/styles.css.map +1 -1
  47. package/dist/{types-NerkPtHS.d.ts → types-CFEtuRWJ.d.ts} +33 -3
  48. package/dist/{types-sOmpCitB.d.cts → types-CMSrWVYM.d.cts} +1 -1
  49. package/dist/{types-sOmpCitB.d.ts → types-CMSrWVYM.d.ts} +1 -1
  50. package/dist/{types-D_jOR3Z2.d.cts → types-DneUoivl.d.cts} +33 -3
  51. package/dist/ux.cjs.map +1 -1
  52. package/dist/ux.d.cts +3 -3
  53. package/dist/ux.d.ts +3 -3
  54. package/dist/ux.js +1 -1
  55. package/package.json +23 -3
  56. package/dist/chunk-AW2QUEL2.js.map +0 -1
  57. package/dist/chunk-D6W5FMCT.js.map +0 -1
  58. package/dist/chunk-L4AX73Q6.js.map +0 -1
  59. package/dist/chunk-U5F22BHV.js.map +0 -1
  60. package/dist/chunk-XETAGLH6.js.map +0 -1
package/dist/engine.cjs CHANGED
@@ -68,8 +68,14 @@ async function runFlow(graph, executors, onEvent = () => {
68
68
  continue;
69
69
  }
70
70
  }
71
- if (node.type === "note") {
72
- onEvent({ type: "node-status", nodeId: node.id, status: "idle", text: "annotation" });
71
+ const visualKind = getNodeKind(node.type ?? "");
72
+ if (node.type === "note" || visualKind?.category === "layout") {
73
+ onEvent({
74
+ type: "node-status",
75
+ nodeId: node.id,
76
+ status: "idle",
77
+ text: visualKind?.category === "layout" ? "lane" : "annotation"
78
+ });
73
79
  continue;
74
80
  }
75
81
  onEvent({ type: "node-status", nodeId: node.id, status: "running" });
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/registry/registry.ts","../src/registry/ports.ts","../src/runtime/run-flow.ts","../src/registry/pause.ts","../src/marketplace/manifest.ts","../src/registry/capabilities.ts","../src/marketplace/fixtures.ts"],"names":["aliases"],"mappings":"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","file":"engine.cjs","sourcesContent":["import type { ConfigField, NodeKindDefinition } from \"./types\";\n\nconst kinds = new Map<string, NodeKindDefinition<any, any, any>>();\n/** alias → canonical name. See `resolveKindId`. */\nconst aliases = new Map<string, string>();\nconst listeners = new Set<() => void>();\n\n/**\n * registerNodeKind — install a node kind in the global registry. Returns\n * an `unregister` function. Calling with the same name replaces the prior\n * registration (handy for HMR).\n *\n * A kind's `name` is its CANONICAL id and is what gets written into saved\n * documents. Publish namespaced (`@fancy/llm_branch`, `@acme/salesforce_upsert`)\n * and list any previous bare names in `aliases`, so graphs saved before the\n * rename keep resolving.\n */\nexport function registerNodeKind<TC = any, TI = any, TO = any>(\n definition: NodeKindDefinition<TC, TI, TO>,\n): () => void {\n kinds.set(definition.name, definition as NodeKindDefinition<any, any, any>);\n for (const alias of definition.aliases ?? []) aliases.set(alias, definition.name);\n notify();\n return () => {\n if (kinds.get(definition.name) === (definition as any)) {\n kinds.delete(definition.name);\n for (const alias of definition.aliases ?? []) {\n if (aliases.get(alias) === definition.name) aliases.delete(alias);\n }\n notify();\n }\n };\n}\n\n/**\n * Resolve any id — canonical or alias — to the canonical one, or null.\n *\n * `kind` is persisted inside every saved graph, so a bare name that two\n * packages could both claim is unfixable after the fact: the ambiguous string\n * is already in the document. Canonical ids are namespaced; aliases exist so\n * documents written before namespacing keep opening.\n */\nexport function resolveKindId(id: string): string | null {\n if (kinds.has(id)) return id;\n const canonical = aliases.get(id);\n return canonical && kinds.has(canonical) ? canonical : null;\n}\n\n/** Get a single kind by canonical id or alias, or null. */\nexport function getNodeKind(name: string): NodeKindDefinition | null {\n const canonical = resolveKindId(name);\n return canonical ? ((kinds.get(canonical) as NodeKindDefinition) ?? null) : null;\n}\n\n/** Every id a kind answers to — canonical first. Used to key node-type maps. */\nexport function kindIds(kind: NodeKindDefinition): string[] {\n return [kind.name, ...(kind.aliases ?? [])];\n}\n\n/** List every registered kind, optionally filtered by category. */\nexport function listNodeKinds(category?: string): NodeKindDefinition[] {\n const all = Array.from(kinds.values()) as NodeKindDefinition[];\n return category ? all.filter((k) => k.category === category) : all;\n}\n\n/** Subscribe to registry changes. Returns an unsubscribe function. */\nexport function onNodeKindsChanged(listener: () => void): () => void {\n listeners.add(listener);\n return () => listeners.delete(listener);\n}\n\nfunction notify(): void {\n for (const l of listeners) l();\n}\n\n/** Fill in defaults from a kind's configSchema for newly-created nodes. */\nexport function defaultConfigFor(kind: NodeKindDefinition): Record<string, unknown> {\n const fromKind = kind.defaultConfig ? { ...(kind.defaultConfig as Record<string, unknown>) } : {};\n for (const field of kind.configSchema ?? []) {\n if (fromKind[field.key] !== undefined) continue;\n if (\"default\" in field && (field as any).default !== undefined) {\n fromKind[field.key] = (field as any).default;\n }\n }\n return fromKind;\n}\n\n/**\n * Validate a config object against a kind's schema. Returns an array of\n * issues (empty = valid). Validation is intentionally light — type\n * coercion + required-field checks. Hosts can layer Zod / Ajv on top.\n */\nexport function validateConfig(\n kind: NodeKindDefinition,\n config: Record<string, unknown>,\n): Array<{ key: string; message: string }> {\n const issues: Array<{ key: string; message: string }> = [];\n for (const field of kind.configSchema ?? []) {\n const value = config[field.key];\n if (field.required && (value === undefined || value === null || value === \"\")) {\n issues.push({ key: field.key, message: `${field.label} is required` });\n continue;\n }\n if (value === undefined || value === null) continue;\n const issue = validateField(field, value);\n if (issue) issues.push({ key: field.key, message: issue });\n }\n return issues;\n}\n\nfunction validateField(field: ConfigField, value: unknown): string | null {\n switch (field.type) {\n case \"text\":\n case \"textarea\":\n case \"expression\":\n case \"credential\":\n return typeof value === \"string\" ? null : `${field.label} must be a string`;\n case \"number\": {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return `${field.label} must be a number`;\n if (field.min !== undefined && value < field.min) return `${field.label} must be >= ${field.min}`;\n if (field.max !== undefined && value > field.max) return `${field.label} must be <= ${field.max}`;\n return null;\n }\n case \"switch\":\n return typeof value === \"boolean\" ? null : `${field.label} must be a boolean`;\n case \"select\": {\n const allowed = field.options.map((o) => o.value);\n return allowed.includes(String(value)) ? null : `${field.label} must be one of ${allowed.join(\", \")}`;\n }\n case \"json\":\n return null; // permissive — just JSON-shaped\n case \"repeater\": {\n if (!Array.isArray(value)) return `${field.label} must be a list`;\n if (field.minItems !== undefined && value.length < field.minItems) {\n return `${field.label} needs at least ${field.minItems}`;\n }\n if (field.maxItems !== undefined && value.length > field.maxItems) {\n return `${field.label} allows at most ${field.maxItems}`;\n }\n // Surface the first offending row so the author knows WHICH one.\n for (let i = 0; i < value.length; i++) {\n const row = value[i];\n if (!row || typeof row !== \"object\" || Array.isArray(row)) {\n return `${field.label} item ${i + 1} must be an object`;\n }\n for (const sub of field.fields) {\n const cell = (row as Record<string, unknown>)[sub.key];\n if (sub.required && (cell === undefined || cell === null || cell === \"\")) {\n return `${field.label} item ${i + 1}: ${sub.label} is required`;\n }\n if (cell === undefined || cell === null) continue;\n const issue = validateField(sub, cell);\n if (issue) return `${field.label} item ${i + 1}: ${issue}`;\n }\n }\n return null;\n }\n case \"keyvalue\": {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return `${field.label} must be a key/value map`;\n }\n const allowed = field.valueOptions?.map((o) => o.value);\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n if (typeof v !== \"string\") return `${field.label}: \"${k}\" must be a string`;\n if (allowed && !allowed.includes(v)) {\n return `${field.label}: \"${k}\" must be one of ${allowed.join(\", \")}`;\n }\n }\n return null;\n }\n case \"document\":\n return null; // opaque to fancy-flow — the host's editor owns its shape\n default:\n return null;\n }\n}\n\n/** Default accents per category. */\nexport function categoryAccent(category: string): string {\n switch (category) {\n case \"trigger\": return \"#10b981\";\n case \"logic\": return \"#f59e0b\";\n case \"data\": return \"#0ea5e9\";\n case \"ai\": return \"#8b5cf6\";\n case \"io\": return \"#3b82f6\";\n case \"human\": return \"#ec4899\";\n case \"output\": return \"#a855f7\";\n default: return \"#71717a\";\n }\n}\n","import type { FlowNode, PortDescriptor } from \"../types\";\nimport type { NodeKindDefinition, PortSpec } from \"./types\";\n\n/**\n * Port resolution — the single place a node's ports are derived, shared by\n * the canvas renderer and the headless runtime.\n *\n * This module is deliberately React-free: `runFlow` (the `/engine` entry)\n * imports it, and the engine bundle must stay free of React.\n *\n * ## Why this is centralized\n *\n * Ports used to be read in two places that disagreed — the canvas consulted\n * `data.outputs ?? kind.outputs`, while the runtime consulted `data.outputs`\n * ONLY and fell back to a single `out` port. A kind that declared branch ports\n * therefore drew correctly and then routed as if it had one output, unless the\n * host remembered to mirror the ports onto every node's `data`. Both callers\n * now go through `resolveNodePorts`, so declared ports and executed ports\n * cannot drift apart.\n */\n\n/**\n * Resolve a `PortSpec` against a config object.\n *\n * A config-driven spec is author-supplied and runs on every render, so a throw\n * is contained: it degrades to \"undeclared\" (letting the caller fall back)\n * rather than taking out the canvas or aborting a run mid-flight.\n */\nexport function resolvePortSpec<TConfig>(\n spec: PortSpec<TConfig> | undefined,\n config: TConfig,\n): PortDescriptor[] | undefined {\n if (spec === undefined) return undefined;\n if (typeof spec !== \"function\") return spec;\n try {\n const resolved = (spec as (c: TConfig) => PortDescriptor[])(config);\n return Array.isArray(resolved) ? resolved : undefined;\n } catch {\n return undefined;\n }\n}\n\n/** Read the config bag off a node, tolerating the FlowNodeData union. */\nexport function nodeConfig(node: Pick<FlowNode, \"data\">): Record<string, unknown> {\n return ((node.data as any)?.config ?? {}) as Record<string, unknown>;\n}\n\n/**\n * Resolve a node's effective ports.\n *\n * Precedence: explicit `data.inputs`/`data.outputs` (a per-node host override)\n * beats the kind's declaration. `undefined` means \"nothing declared\" — the\n * caller applies its own category default.\n */\nexport function resolveNodePorts(\n node: Pick<FlowNode, \"data\">,\n kind?: Pick<NodeKindDefinition<any>, \"inputs\" | \"outputs\">,\n): { inputs?: PortDescriptor[]; outputs?: PortDescriptor[] } {\n const config = nodeConfig(node);\n const data = node.data as any;\n return {\n inputs: data?.inputs ?? resolvePortSpec(kind?.inputs, config),\n outputs: data?.outputs ?? resolvePortSpec(kind?.outputs, config),\n };\n}\n","import type {\n ExecutorRegistry,\n FlowEdge,\n FlowGraph,\n FlowNode,\n NodeExecutor,\n RunEvent,\n} from \"../types\";\n// Both modules are React-free by design — the `/engine` entry must not pull in\n// React. Import them directly rather than via the `registry` barrel, which\n// re-exports the RegistryNode component.\nimport { getNodeKind, kindIds } from \"../registry/registry\";\nimport { resolveNodePorts } from \"../registry/ports\";\n\nexport type RunOptions = {\n /** Stop the run after this many ms. Default: no timeout. */\n timeoutMs?: number;\n /** Abort signal — host can cancel the run. */\n signal?: AbortSignal;\n /** Initial inputs supplied to entry-point nodes (no incoming edges). */\n initialInputs?: Record<string, Record<string, unknown>>;\n /** Nesting depth — set by `subflow` when it runs a child graph. */\n depth?: number;\n};\n\nexport type RunResult = {\n ok: boolean;\n /** Outputs collected per node, keyed by node id. */\n outputs: Record<string, unknown>;\n /** Error captured if any node threw. */\n error?: string;\n};\n\n/**\n * runFlow — topological execution of a FlowGraph against an ExecutorRegistry.\n *\n * Each node runs once, when all upstream nodes have produced outputs on the\n * connected ports. Decision nodes (or any executor that returns `{ branch:\n * 'true' }`) can short-circuit specific output ports — only edges leaving\n * an \"active\" port propagate to downstream nodes.\n *\n * Cycles are detected and abort the run with an error.\n *\n * The `onEvent` callback receives a stream of `RunEvent`s — wire it to a\n * status feed, log panel, or store.\n */\nexport async function runFlow(\n graph: FlowGraph,\n executors: ExecutorRegistry,\n onEvent: (event: RunEvent) => void = () => {},\n options: RunOptions = {},\n): Promise<RunResult> {\n const { signal, initialInputs = {}, timeoutMs, depth = 0 } = options;\n const outputs: Record<string, unknown> = {};\n const portValues = new Map<string, unknown>(); // key: `${nodeId}:${portId}`\n const completed = new Set<string>();\n const errors: string[] = [];\n\n // Topological order via Kahn's algorithm. We allow nodes to run as soon\n // as their incoming edges' source ports have produced values, so the\n // order here is just a deterministic baseline used for cycle detection.\n const order = topoSort(graph);\n if (order === null) {\n const msg = \"Cycle detected in flow graph — aborting.\";\n onEvent({ type: \"run-error\", error: msg });\n return { ok: false, outputs, error: msg };\n }\n\n const incomingByNode = indexIncoming(graph.edges);\n const timer = timeoutMs ? setTimeout(() => errors.push(`Run timed out after ${timeoutMs}ms`), timeoutMs) : null;\n\n onEvent({ type: \"run-start\" });\n\n try {\n for (const node of order) {\n if (signal?.aborted) throw new Error(\"aborted\");\n if (errors.length) break;\n\n const incoming = incomingByNode.get(node.id) ?? [];\n\n // Run a node once any upstream branch reaches it. We iterate in\n // topological order, so by the time we reach this node every upstream\n // node has been processed — each incoming edge is therefore *settled*\n // (active or dead, never still-pending). Requiring ALL incoming edges to\n // be active wrongly skipped MERGE POINTS: when a Decision routes down one\n // branch, the other branch's edge stays dead forever, so an `every` check\n // skipped the shared continuation node and halted the run after the first\n // branch (#1). Run when AT LEAST ONE incoming edge is active —\n // collectInputs() only reads from the active ones. A genuine parallel\n // join still works: in topo order both of its inputs are already active.\n if (incoming.length > 0) {\n const anyActive = incoming.some((e) => portValues.has(`${e.source}:${e.sourceHandle ?? \"out\"}`));\n if (!anyActive) {\n onEvent({ type: \"node-status\", nodeId: node.id, status: \"idle\", text: \"skipped\" });\n continue;\n }\n }\n\n // Note nodes are annotations — never executed.\n if (node.type === \"note\") {\n onEvent({ type: \"node-status\", nodeId: node.id, status: \"idle\", text: \"annotation\" });\n continue;\n }\n\n onEvent({ type: \"node-status\", nodeId: node.id, status: \"running\" });\n\n const inputs = collectInputs(node, incoming, portValues, initialInputs);\n const exec = pickExecutor(executors, node);\n if (!exec) {\n const msg = `No executor registered for kind=${node.type}`;\n errors.push(msg);\n onEvent({ type: \"node-status\", nodeId: node.id, status: \"error\", text: msg });\n onEvent({ type: \"log\", nodeId: node.id, level: \"error\", message: msg });\n break;\n }\n\n try {\n const result = await Promise.resolve(\n exec({\n node,\n inputs,\n abort: (reason) => { throw new Error(reason ?? \"aborted\"); },\n emit: onEvent,\n depth,\n }),\n );\n outputs[node.id] = result;\n\n // Decide which output ports were activated. Three conventions:\n // 1) If result is `{ __port: \"out\", value: x }`, only that port emits.\n // 2) If result has `branch: <portId>`, only that port emits (decision sugar).\n // 3) Otherwise, the value is published on every declared output port.\n const activated = activatedPorts(node, result);\n for (const portId of activated.ports) {\n portValues.set(`${node.id}:${portId}`, activated.value);\n onEvent({ type: \"node-output\", nodeId: node.id, portId, value: activated.value });\n }\n completed.add(node.id);\n onEvent({ type: \"node-status\", nodeId: node.id, status: \"done\" });\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n errors.push(msg);\n onEvent({ type: \"node-status\", nodeId: node.id, status: \"error\", text: msg });\n onEvent({ type: \"log\", nodeId: node.id, level: \"error\", message: msg });\n break;\n }\n }\n } finally {\n if (timer) clearTimeout(timer);\n }\n\n const ok = errors.length === 0;\n onEvent({ type: \"run-end\", ok });\n return ok ? { ok, outputs } : { ok, outputs, error: errors[0] };\n}\n\nfunction indexIncoming(edges: FlowEdge[]): Map<string, FlowEdge[]> {\n const map = new Map<string, FlowEdge[]>();\n for (const e of edges) {\n const list = map.get(e.target) ?? [];\n list.push(e);\n map.set(e.target, list);\n }\n return map;\n}\n\nfunction topoSort(graph: FlowGraph): FlowNode[] | null {\n const inDegree = new Map<string, number>();\n for (const n of graph.nodes) inDegree.set(n.id, 0);\n for (const e of graph.edges) inDegree.set(e.target, (inDegree.get(e.target) ?? 0) + 1);\n const queue: string[] = [];\n for (const [id, d] of inDegree) if (d === 0) queue.push(id);\n const ordered: string[] = [];\n while (queue.length) {\n const id = queue.shift()!;\n ordered.push(id);\n for (const e of graph.edges) {\n if (e.source !== id) continue;\n const next = (inDegree.get(e.target) ?? 0) - 1;\n inDegree.set(e.target, next);\n if (next === 0) queue.push(e.target);\n }\n }\n if (ordered.length !== graph.nodes.length) return null;\n const byId = new Map(graph.nodes.map((n) => [n.id, n]));\n return ordered.map((id) => byId.get(id)!).filter(Boolean);\n}\n\nfunction collectInputs(\n node: FlowNode,\n incoming: FlowEdge[],\n portValues: Map<string, unknown>,\n initial: Record<string, Record<string, unknown>>,\n): Record<string, unknown> {\n const inputs: Record<string, unknown> = { ...(initial[node.id] ?? {}) };\n for (const e of incoming) {\n const portId = e.targetHandle ?? \"in\";\n const val = portValues.get(`${e.source}:${e.sourceHandle ?? \"out\"}`);\n inputs[portId] = val;\n }\n return inputs;\n}\n\nfunction pickExecutor(\n executors: ExecutorRegistry,\n node: FlowNode,\n): NodeExecutor | undefined {\n if (executors[node.id]) return executors[node.id];\n if (node.type && executors[node.type]) return executors[node.type];\n\n // Try every id the kind answers to. Kinds are namespaced (`@fancy/switch_case`)\n // while a host may have bound its executor under the bare name it used before\n // — or vice versa. Without this, the rename would silently stop matching and\n // the node would fall through to `*` or simply not run: a breaking change\n // wearing the costume of a rename.\n const kind = node.type ? getNodeKind(node.type) : null;\n if (kind) {\n for (const id of kindIds(kind)) {\n if (executors[id]) return executors[id];\n }\n }\n\n return executors[\"*\"];\n}\n\nfunction activatedPorts(node: FlowNode, result: unknown): { ports: string[]; value: unknown } {\n if (result && typeof result === \"object\") {\n const r = result as Record<string, unknown>;\n if (typeof r.__port === \"string\") {\n return { ports: [r.__port], value: r.value };\n }\n if (typeof r.branch === \"string\") {\n return { ports: [r.branch], value: r.value ?? r };\n }\n }\n // Resolve through the shared helper so the ports the runtime activates are\n // the same ones the canvas drew — including config-driven ports, which the\n // node's `data` does not carry. Falls back to a lone `out` when a node\n // declares nothing.\n const kind = getNodeKind((node.data as any)?.kind ?? node.type ?? \"\") ?? undefined;\n const declared = resolveNodePorts(node, kind).outputs?.map((p) => p.id);\n return { ports: declared?.length ? declared : [\"out\"], value: result };\n}\n","/**\n * The human-pause contract.\n *\n * A workflow that waits for a person is not an error, but it travels the same\n * channel as one: the executor aborts, the engine records a reason string, and\n * the durable runner decides whether that string meant \"failed\" or \"waiting\".\n *\n * That seam existed before this module, as two `str_starts_with` checks in the\n * Laravel run job against constants owned by two BUILTIN executors. It worked,\n * and it was invisible: a third-party human-input node had no way to announce\n * that it pauses, and nothing stopped a refactor from removing the mechanism\n * out from under published packages. Reported by the MOIC Suite consumer, who\n * needed exactly that and had to reach for a private constant to get it.\n *\n * So the encoding is now public, typed, and versioned by prefix rather than\n * implied. The wire format stays a plain string on purpose — it survives the\n * existing abort → `RunResult.error` path unchanged, crosses a queue boundary,\n * and decodes identically in PHP, none of which a thrown class would do.\n *\n * @see decodePause — the one function a durable runner needs.\n */\n\n/**\n * What the run is waiting for.\n *\n * `approval` and `input` are the shapes both runtimes ship. The type stays open\n * because the whole point is that a marketplace node can define its own —\n * a signature step, a payment confirmation, a review queue — and a runner that\n * does not recognise one should report it rather than guess.\n */\nexport type PauseAwaiting = \"approval\" | \"input\" | (string & {});\n\n/** A run halted, waiting for a person. */\nexport type PauseSignal = {\n /** The node that paused — where a submission gets injected on resume. */\n nodeId: string;\n awaiting: PauseAwaiting;\n /**\n * Kind-supplied context for whoever renders the wait — a form schema, the\n * question being asked, a diff to approve. Must be JSON-serializable: it\n * crosses a queue boundary and, for durable runs, a database column.\n */\n detail?: unknown;\n};\n\n/** Marks a reason string as a pause rather than a failure. */\nexport const PAUSE_PREFIX = \"fancy-flow:pause:\";\n\n/**\n * Reason prefixes shipped before this contract, kept decodable forever.\n *\n * These are what `DurableApprovalExecutor` and `DurableUserInputExecutor`\n * emitted, and they are written into the `error` column of every run that\n * paused under an older version. Dropping them would strand those runs\n * mid-flight — a resume path that only works for new runs is not a resume path.\n */\nexport const LEGACY_PAUSE_PREFIXES: ReadonlyArray<readonly [string, PauseAwaiting]> = [\n [\"awaiting-approval:\", \"approval\"],\n [\"awaiting-input:\", \"input\"],\n];\n\n/**\n * Encode a pause as the reason string an executor aborts with.\n *\n * The payload is JSON rather than delimited fields because a node id may\n * contain a colon, and a positional encoding that breaks on user data is the\n * kind of bug that only shows up in someone else's graph.\n */\nexport function encodePause(signal: PauseSignal): string {\n const { nodeId, awaiting, detail } = signal;\n return PAUSE_PREFIX + JSON.stringify(detail === undefined ? { nodeId, awaiting } : { nodeId, awaiting, detail });\n}\n\n/**\n * Decode a run's error reason into a pause, or null if it was a real failure.\n *\n * This is the whole contract from a runner's side: call it on `result.error`,\n * and if it returns non-null, persist the run as waiting on `signal.nodeId`\n * instead of failing it. Accepts the legacy prefixes, so a runner written\n * against this handles runs that paused under an older version.\n */\nexport function decodePause(reason: string | null | undefined): PauseSignal | null {\n if (typeof reason !== \"string\") return null;\n\n if (reason.startsWith(PAUSE_PREFIX)) {\n const body = reason.slice(PAUSE_PREFIX.length);\n try {\n const parsed = JSON.parse(body) as Partial<PauseSignal>;\n // A malformed payload is a corrupt pause, not a failure to report as a\n // crash — but it is also not something to invent a node id for.\n if (typeof parsed?.nodeId !== \"string\" || typeof parsed?.awaiting !== \"string\") return null;\n return \"detail\" in parsed\n ? { nodeId: parsed.nodeId, awaiting: parsed.awaiting, detail: parsed.detail }\n : { nodeId: parsed.nodeId, awaiting: parsed.awaiting };\n } catch {\n return null;\n }\n }\n\n for (const [prefix, awaiting] of LEGACY_PAUSE_PREFIXES) {\n if (reason.startsWith(prefix)) {\n return { nodeId: reason.slice(prefix.length), awaiting };\n }\n }\n\n return null;\n}\n\n/** True when a run's error reason is actually a pause. */\nexport function isPause(reason: string | null | undefined): boolean {\n return decodePause(reason) !== null;\n}\n\n/**\n * Abort the current node as a pause.\n *\n * Called from inside an executor with its own context. Node authors should\n * reach for this rather than hand-encoding a reason, so the format stays ours\n * to change:\n *\n * ```ts\n * const values = ctx.inputs.values;\n * if (values === undefined) pauseForHuman(ctx, \"input\", { fields });\n * return values;\n * ```\n *\n * Note the `undefined` check — an empty submission (`{}`) is a real answer and\n * must resume. Truthiness here pauses forever on an empty form.\n */\nexport function pauseForHuman(\n ctx: { node: { id: string }; abort: (reason?: string) => never },\n awaiting: PauseAwaiting,\n detail?: unknown,\n): never {\n return ctx.abort(encodePause({ nodeId: ctx.node.id, awaiting, detail }));\n}\n","/**\n * The node package manifest — what a marketplace node declares about itself.\n *\n * A node is not one artifact. It is a kind definition (palette entry, config\n * schema, ports, renderer) plus an executor for EACH runtime the consumer runs.\n * A package shipping only a TS executor is unusable to anyone executing on PHP,\n * and without a manifest that is invisible until a run fails. Requested by the\n * MOIC Suite consumer (fancy-flow#2 §2), who runs the editor in TS and executes\n * in PHP and hit exactly this.\n *\n * The manifest is data, not code: the registry, the CLI, and the MCP all read\n * it without executing anything a package author wrote.\n *\n * ## Why the engine range lives per runtime\n *\n * The first cut of this manifest carried ONE `fancyFlow` range, and it was\n * wrong: the two engines version independently, so a single range cannot say\n * \"needs npm >=0.11 AND php >=0.5\". A package supporting both runtimes would\n * install cleanly against a host whose OTHER runtime was too old — the 0.9.0\n * failure shape wearing a manifest. The range belongs inside each runtime.\n */\n\nimport type { PauseAwaiting } from \"../registry/pause\";\n\n/** The current manifest schema version. Bump only on a breaking shape change. */\nexport const NODE_MANIFEST_SCHEMA_VERSION = 1;\n\n/**\n * A runtime a node can implement.\n *\n * Open rather than a closed union — the PHP and Node twins are what exist\n * today, but the point of a manifest is that a runtime we haven't written can\n * declare itself without a release here.\n */\nexport type NodeRuntimeId = \"ts\" | \"php\" | (string & {});\n\n/**\n * How one runtime provides this node, and which engine version it needs.\n *\n * `entry` and `package` are both here because the two ecosystems install\n * differently — a module path within the package for TS, a Composer\n * requirement for PHP — and pretending otherwise just moves the problem into\n * the CLI. Exactly one is required.\n */\nexport type NodeRuntimeSpec = {\n /** Module path within the package (TS-style runtimes). */\n entry?: string;\n /** Dependency requirement resolved by that ecosystem (PHP/Composer-style). */\n package?: string;\n /** Semver range of THIS runtime's engine. Required — see the module note. */\n engine: string;\n};\n\n/**\n * Whether a capability must be wired for the node to work at all.\n *\n * `required` is checked at AUTHOR time, not run time. The failure that hurts is\n * a node that installs fine, authors fine, and silently no-ops during a run —\n * the same silence as a routing bug. An editor can grey the node and say which\n * capability the host never registered.\n */\nexport type CapabilityRequirement = \"required\" | \"optional\";\n\n/**\n * Whether a node is safe to run again.\n *\n * Durable runs RETRY. A node that writes needs to say so, or a host has to pick\n * one retry policy for every node and get it wrong somewhere.\n */\nexport type SideEffects = \"none\" | \"idempotent\" | \"unsafe-to-replay\";\n\nexport type NodePackageManifest = {\n /** Must equal `NODE_MANIFEST_SCHEMA_VERSION`. */\n schemaVersion: number;\n /** Package name, as installed (`@acme/fancy-flow-salesforce`). */\n name: string;\n /**\n * The canonical kind id this package provides — namespaced, and the string\n * that gets persisted into every document using it.\n */\n kind: string;\n /**\n * Previous ids this kind still answers to.\n *\n * Core renamed `llm_branch` to `llm_router` and kept every old id working.\n * Third-party packages will rename too, and their documents break the same\n * way core's would have — so packages get the same escape hatch, otherwise\n * only first-party nodes can rename safely.\n */\n aliases?: string[];\n /**\n * Version of this node's CONFIG shape, independent of the document schema.\n *\n * A node's config evolves on its own clock. Without a declared version, every\n * executor accretes hand-written read-fallbacks forever (MOIC carries one for\n * `routes[].key` → `routes[].port`), because nothing canonicalises old config\n * the way import canonicalises kind ids.\n */\n configVersion?: number;\n /** Per-runtime entrypoints and engine ranges. */\n runtimes: Partial<Record<NodeRuntimeId, NodeRuntimeSpec>>;\n /**\n * Host capabilities this node needs, and whether each is mandatory.\n *\n * Declared so the CLI and the editor can say what to wire BEFORE a run,\n * rather than the node silently no-opping or crashing mid-run.\n */\n capabilities?: Record<string, CapabilityRequirement>;\n /**\n * Path to this node's golden fixtures, relative to the package root.\n *\n * REQUIRED. Every runtime the package claims runs these same cases, which is\n * what makes \"behaves identically on both runtimes\" verified rather than\n * asserted. See `./fixtures`.\n */\n fixtures: string;\n /**\n * Declares the node halts for a person. Mirrors `NodeKindDefinition`.\n *\n * A host-planning fact, not a node internal: a parent that embeds workflows\n * needs to reject a child that can pause, because a paused child wedges the\n * parent — and discovering that at run time means watching a run park.\n */\n pausesForHuman?: PauseAwaiting;\n /** Whether this node is safe to replay. See `SideEffects`. */\n sideEffects?: SideEffects;\n /** One-line summary — what `search_nodes` matches against. */\n description?: string;\n /**\n * Assigned by the registry, never by the author. Present in a manifest being\n * submitted for publication, it is a claim to a trust signal the author does\n * not get to make.\n */\n verified?: boolean;\n};\n\nexport type ManifestProblem = {\n level: \"error\" | \"warning\";\n field: string;\n message: string;\n};\n\nexport type ManifestValidation = {\n /** True when there are no `error`-level problems. Warnings do not block. */\n ok: boolean;\n manifest?: NodePackageManifest;\n problems: ManifestProblem[];\n};\n\n/** Reserved for first-party packages; the registry rejects other claimants. */\nconst FIRST_PARTY_SCOPE = \"@particle-academy/\";\n\n/** `@scope/name` — the shape 0.11.0 made canonical for kind ids. */\nconst NAMESPACED_KIND = /^@[a-z0-9][a-z0-9._-]*\\/[a-z0-9][a-z0-9._-]*$/i;\n\nconst SIDE_EFFECTS: readonly string[] = [\"none\", \"idempotent\", \"unsafe-to-replay\"];\nconst REQUIREMENTS: readonly string[] = [\"required\", \"optional\"];\n\nfunction err(field: string, message: string): ManifestProblem {\n return { level: \"error\", field, message };\n}\n\nfunction warn(field: string, message: string): ManifestProblem {\n return { level: \"warning\", field, message };\n}\n\n/**\n * Validate a manifest read from disk or a registry.\n *\n * Returns every problem rather than throwing on the first, because an author\n * fixing a package wants the whole list — a validator that reveals one error\n * per run turns a five-minute fix into five round trips.\n */\nexport function validateNodeManifest(input: unknown): ManifestValidation {\n const problems: ManifestProblem[] = [];\n\n if (typeof input !== \"object\" || input === null || Array.isArray(input)) {\n return { ok: false, problems: [err(\"\", \"Manifest must be a JSON object.\")] };\n }\n\n const m = input as Record<string, unknown>;\n\n // Version first: an unknown version means every other check below is\n // guessing at a shape we do not know, so say so plainly instead of\n // half-reading it and reporting confident nonsense about the rest.\n if (m.schemaVersion !== NODE_MANIFEST_SCHEMA_VERSION) {\n if (typeof m.schemaVersion !== \"number\") {\n problems.push(err(\"schemaVersion\", `Required, and must be ${NODE_MANIFEST_SCHEMA_VERSION}.`));\n } else {\n return {\n ok: false,\n problems: [\n err(\n \"schemaVersion\",\n `Unsupported manifest version ${m.schemaVersion}; this fancy-flow understands ${NODE_MANIFEST_SCHEMA_VERSION}. Upgrade fancy-flow to install this node.`,\n ),\n ],\n };\n }\n }\n\n if (typeof m.name !== \"string\" || m.name.trim() === \"\") {\n problems.push(err(\"name\", \"Required — the package name as installed.\"));\n }\n\n validateKind(m.kind, problems);\n validateAliases(m.aliases, problems);\n\n if (m.configVersion !== undefined && (typeof m.configVersion !== \"number\" || !Number.isInteger(m.configVersion))) {\n problems.push(err(\"configVersion\", \"Must be an integer.\"));\n }\n\n // A leftover single range from the pre-per-runtime shape. Worth naming\n // explicitly rather than ignoring — it silently means \"no engine constraint\".\n if (m.fancyFlow !== undefined) {\n problems.push(\n err(\n \"fancyFlow\",\n \"A single engine range cannot express the split — it cannot say \\\"needs ts >=0.15 AND php >=0.7\\\". Move the range into each entry of `runtimes` as `engine`.\",\n ),\n );\n }\n\n validateRuntimes(m.runtimes, problems);\n\n // Fixtures: the publish gate. Cross-runtime drift does not fail loudly —\n // it completes, down one path, with no error — so it has to be caught by\n // something that runs, not by review.\n if (typeof m.fixtures !== \"string\" || m.fixtures.trim() === \"\") {\n problems.push(\n err(\"fixtures\", \"Required — path to the node's golden fixtures. Every claimed runtime runs them, which is what makes cross-runtime parity verified rather than claimed.\"),\n );\n }\n\n validateCapabilities(m.capabilities, problems);\n\n if (m.sideEffects !== undefined && !SIDE_EFFECTS.includes(m.sideEffects as string)) {\n problems.push(err(\"sideEffects\", `Must be one of: ${SIDE_EFFECTS.join(\", \")}.`));\n }\n\n if (m.verified !== undefined) {\n problems.push(\n err(\"verified\", \"Assigned by the registry, not the package. Remove it — a package cannot vouch for itself.\"),\n );\n }\n\n const ok = !problems.some((p) => p.level === \"error\");\n return ok ? { ok, manifest: m as unknown as NodePackageManifest, problems } : { ok, problems };\n}\n\nfunction validateKind(kind: unknown, problems: ManifestProblem[]): void {\n if (typeof kind !== \"string\" || kind.trim() === \"\") {\n problems.push(err(\"kind\", \"Required — the canonical kind id this package provides.\"));\n return;\n }\n if (!NAMESPACED_KIND.test(kind)) {\n // Un-namespaced ids are the one mistake that cannot be fixed after the\n // fact: the ambiguous string is already written into saved documents.\n problems.push(\n err(\"kind\", `\"${kind}\" must be namespaced as @scope/name — a bare id makes stored graphs ambiguous, and that is unfixable once documents carry it.`),\n );\n return;\n }\n if (kind.startsWith(FIRST_PARTY_SCOPE)) {\n problems.push(\n warn(\"kind\", `${FIRST_PARTY_SCOPE}* is reserved for first-party nodes; the registry will reject this unless the package is first-party.`),\n );\n }\n}\n\nfunction validateAliases(aliases: unknown, problems: ManifestProblem[]): void {\n if (aliases === undefined) return;\n\n if (!Array.isArray(aliases) || aliases.some((a) => typeof a !== \"string\" || a.trim() === \"\")) {\n problems.push(err(\"aliases\", \"Must be an array of non-empty id strings.\"));\n }\n}\n\nfunction validateRuntimes(runtimes: unknown, problems: ManifestProblem[]): void {\n if (typeof runtimes !== \"object\" || runtimes === null || Array.isArray(runtimes)) {\n problems.push(err(\"runtimes\", \"Required — an object of runtime id to { entry | package, engine }.\"));\n return;\n }\n\n const entries = Object.entries(runtimes as Record<string, unknown>);\n if (entries.length === 0) {\n problems.push(err(\"runtimes\", \"A node that implements no runtime cannot execute anywhere.\"));\n return;\n }\n\n for (const [runtime, spec] of entries) {\n if (typeof spec !== \"object\" || spec === null || Array.isArray(spec)) {\n problems.push(err(`runtimes.${runtime}`, \"Must be an object of { entry | package, engine }.\"));\n continue;\n }\n\n const s = spec as Record<string, unknown>;\n const hasEntry = typeof s.entry === \"string\" && s.entry.trim() !== \"\";\n const hasPackage = typeof s.package === \"string\" && s.package.trim() !== \"\";\n\n if (!hasEntry && !hasPackage) {\n problems.push(err(`runtimes.${runtime}`, \"Needs `entry` (a module path) or `package` (a dependency requirement).\"));\n }\n if (hasEntry && hasPackage) {\n problems.push(err(`runtimes.${runtime}`, \"Declare `entry` or `package`, not both — which one is authoritative is otherwise ambiguous.\"));\n }\n if (typeof s.engine !== \"string\" || s.engine.trim() === \"\") {\n problems.push(\n err(`runtimes.${runtime}.engine`, `Required — the semver range of the ${runtime} engine. Without it, this node installs against a ${runtime} engine too old to run it.`),\n );\n }\n }\n}\n\nfunction validateCapabilities(capabilities: unknown, problems: ManifestProblem[]): void {\n if (capabilities === undefined) return;\n\n if (typeof capabilities !== \"object\" || capabilities === null || Array.isArray(capabilities)) {\n problems.push(\n err(\"capabilities\", 'Must be an object of capability id to \"required\" | \"optional\" — a bare list cannot say whether the node works without one.'),\n );\n return;\n }\n\n for (const [id, requirement] of Object.entries(capabilities as Record<string, unknown>)) {\n if (!REQUIREMENTS.includes(requirement as string)) {\n problems.push(err(`capabilities.${id}`, `Must be \"required\" or \"optional\".`));\n }\n }\n}\n\n/**\n * Check a node against the runtimes a host executes on, and their versions.\n *\n * Two failures live here, and both are errors because the node genuinely\n * cannot run: a runtime the package does not implement at all, and a runtime\n * it implements against an engine newer than the host's.\n *\n * `engineVersions` is optional — pass what the host knows. An unchecked range\n * is reported as a warning rather than passed over silently, because \"we did\n * not check\" and \"it is fine\" must not look the same.\n */\nexport function checkRuntimeSupport(\n manifest: Pick<NodePackageManifest, \"kind\" | \"runtimes\">,\n hostRuntimes: readonly string[],\n engineVersions?: Readonly<Record<string, string>>,\n): ManifestProblem[] {\n const runtimes = manifest.runtimes ?? {};\n const provided = Object.keys(runtimes);\n const problems: ManifestProblem[] = [];\n\n const missing = hostRuntimes.filter((r) => !provided.includes(r));\n if (missing.length > 0) {\n problems.push(\n err(\n \"runtimes\",\n `${manifest.kind} implements ${provided.join(\", \") || \"no runtime\"} but this project executes on ${missing.join(\", \")}. The node would install, appear in the palette, and then fail to run.`,\n ),\n );\n }\n\n for (const runtime of hostRuntimes) {\n const spec = (runtimes as Record<string, NodeRuntimeSpec | undefined>)[runtime];\n if (!spec) continue;\n\n const hostVersion = engineVersions?.[runtime];\n if (hostVersion === undefined) {\n problems.push(\n warn(`runtimes.${runtime}.engine`, `${manifest.kind} needs ${runtime} engine ${spec.engine}; this host did not report its ${runtime} version, so the range was not checked.`),\n );\n continue;\n }\n\n if (!satisfiesRange(hostVersion, spec.engine)) {\n problems.push(\n err(`runtimes.${runtime}.engine`, `${manifest.kind} needs ${runtime} engine ${spec.engine}, but this host runs ${hostVersion}.`),\n );\n }\n }\n\n return problems;\n}\n\n/**\n * Minimal semver range check — `^x.y.z`, `~x.y.z`, `>=x.y.z`, `x.y.z`, `*`.\n *\n * Deliberately small: this runs in the CLI and in CI, and pulling a semver\n * library into the engine for one comparison is not worth the dependency. It\n * covers the forms a manifest actually uses; anything it cannot parse is\n * treated as unsatisfied rather than silently passed, so an unparseable range\n * fails loudly instead of waving a node through.\n */\nexport function satisfiesRange(version: string, range: string): boolean {\n const trimmed = range.trim();\n if (trimmed === \"*\" || trimmed === \"\") return true;\n\n const v = parseVersion(version);\n if (!v) return false;\n\n for (const clause of trimmed.split(\"||\").map((c) => c.trim())) {\n if (satisfiesClause(v, clause)) return true;\n }\n return false;\n}\n\nfunction satisfiesClause(v: [number, number, number], clause: string): boolean {\n const m = /^(\\^|~|>=|>|<=|<|=)?\\s*v?(\\d+)(?:\\.(\\d+))?(?:\\.(\\d+))?/.exec(clause);\n if (!m) return false;\n\n const op = m[1] ?? \"=\";\n const target: [number, number, number] = [Number(m[2]), Number(m[3] ?? 0), Number(m[4] ?? 0)];\n const cmp = compare(v, target);\n\n switch (op) {\n case \">=\":\n return cmp >= 0;\n case \">\":\n return cmp > 0;\n case \"<=\":\n return cmp <= 0;\n case \"<\":\n return cmp < 0;\n case \"=\":\n return cmp === 0;\n case \"~\":\n // Same major+minor, patch may rise.\n return cmp >= 0 && v[0] === target[0] && v[1] === target[1];\n case \"^\":\n // Below 1.0.0 a minor bump is breaking, so ^0.5 means 0.5.x — which is\n // the range every pre-1.0 package in this suite actually needs.\n if (target[0] === 0) return cmp >= 0 && v[0] === 0 && v[1] === target[1];\n return cmp >= 0 && v[0] === target[0];\n default:\n return false;\n }\n}\n\nfunction parseVersion(version: string): [number, number, number] | null {\n const m = /^v?(\\d+)\\.(\\d+)(?:\\.(\\d+))?/.exec(version.trim());\n return m ? [Number(m[1]), Number(m[2]), Number(m[3] ?? 0)] : null;\n}\n\nfunction compare(a: [number, number, number], b: [number, number, number]): number {\n for (let i = 0; i < 3; i++) {\n if (a[i] !== b[i]) return a[i] < b[i] ? -1 : 1;\n }\n return 0;\n}\n\n/**\n * Check that every capability a node needs is wired.\n *\n * A `required` capability that is missing is an ERROR — that is the whole point\n * of the requirement level. It is meant to be surfaced at author time, so an\n * editor can grey the node and name what the host never registered, rather than\n * the node installing cleanly and silently no-opping during a run.\n *\n * An `optional` one is a warning: the node still works, with less.\n */\nexport function checkCapabilities(\n manifest: Pick<NodePackageManifest, \"kind\" | \"capabilities\">,\n available: Readonly<Record<string, boolean>>,\n): ManifestProblem[] {\n const needed = manifest.capabilities ?? {};\n const problems: ManifestProblem[] = [];\n\n for (const [id, requirement] of Object.entries(needed)) {\n if (available[id] === true) continue;\n\n problems.push(\n requirement === \"required\"\n ? err(\"capabilities\", `${manifest.kind} requires the ${id} capability, which this host has not registered. The node cannot run here.`)\n : warn(\"capabilities\", `${manifest.kind} can use the ${id} capability, which this host has not registered. The node runs with reduced behaviour.`),\n );\n }\n\n return problems;\n}\n","import type { FlowGraph } from \"../types\";\n\n/**\n * Host capabilities — the services core nodes need but must never depend on.\n *\n * A node that imports a provider SDK forces every consumer to install it: a\n * workflow app that never calls a model should not inherit an LLM dependency.\n * So core declares the CONTRACT and the host supplies the implementation, the\n * same arrangement `renderDocumentField` already uses for documents.\n *\n * That keeps opinionated nodes in core without their opinions: `llm_branch`\n * ships the routing semantics, port derivation and config UI, while whichever\n * client the host registers — Prism, an OpenAI SDK, a local model, a fake in a\n * test — decides how the question actually gets asked.\n *\n * Registration is deliberately explicit and typed per capability rather than a\n * stringly-keyed bag, so a missing one is a clear error at the seam instead of\n * an undefined somewhere downstream.\n */\n\n// ── LLM ─────────────────────────────────────────────────────────────────────\n\nexport type LlmRoute = { port: string; description?: string };\n\nexport type LlmRouteRequest = {\n /** Optional framing for the decision. */\n system?: string;\n /** What the model is deciding about. */\n prompt: string;\n /** The ports it must choose between. */\n routes: LlmRoute[];\n provider?: string;\n model?: string;\n /** Host-resolved credential reference, never a raw key. */\n credential?: string;\n};\n\nexport type LlmRouteChoice = {\n /** Must be one of the requested route ports. */\n port: string;\n /** Why — carried down the chosen port so a run is explainable afterwards. */\n reason?: string;\n};\n\n/**\n * The only thing core asks of an LLM: given routes, pick one.\n *\n * Deliberately not a general chat interface. A narrow contract is one a host\n * can satisfy in a few lines over any SDK, and it keeps the choice\n * machine-checkable — an implementation should constrain the model to the\n * declared ports (structured output / enum) rather than parsing prose.\n */\nexport type LlmClient = {\n chooseRoute: (request: LlmRouteRequest) => Promise<LlmRouteChoice> | LlmRouteChoice;\n};\n\nlet llmClient: LlmClient | null = null;\n\n/** Install the host's LLM client. Returns an unregister function. */\nexport function registerLlmClient(client: LlmClient): () => void {\n llmClient = client;\n return () => {\n if (llmClient === client) llmClient = null;\n };\n}\n\nexport function getLlmClient(): LlmClient | null {\n return llmClient;\n}\n\n// ── Workflow resolution ─────────────────────────────────────────────────────\n\n/**\n * Why a workflow reference could not be resolved.\n *\n * `missing` and `version-mismatch` are deliberately distinct. Collapsing them\n * into a bare null makes \"no such workflow\" indistinguishable from \"that\n * workflow exists, but it is not the one you pinned\" — and the second wants an\n * error naming both versions, because it is the interesting failure.\n */\nexport type WorkflowResolutionFailure = {\n reason: \"missing\" | \"version-mismatch\";\n /** The version the host actually holds, when it holds one. */\n available?: number;\n message?: string;\n};\n\nexport type WorkflowResolution = FlowGraph | WorkflowResolutionFailure | null;\n\n/**\n * Resolve a workflow reference to a runnable graph.\n *\n * `subflow` names another workflow rather than embedding it, so the host owns\n * where workflows live — a database, a file, an API.\n *\n * ## Why `version` is here\n *\n * A workflow another workflow depends on is an INTERFACE, and interfaces need\n * pins. Without a version, a parent goes on calling `invoice-triage`, someone\n * edits that child, and the parent now runs different logic having reported\n * success the whole time — correct-looking, no error, wrong behaviour. The same\n * failure family as the 0.9.0 routing divergence.\n *\n * The parameter lives on the resolver rather than being encoded into the ref\n * string (`invoice-triage@3`) because a stringly-typed protocol is one every\n * host invents differently — the \"three vocabularies for one node\" problem.\n *\n * Raised by the MOIC Suite consumer, whose `workflow_ref` pins versions and\n * fails loudly on mismatch. Their point: a host COULD NOT implement pinning\n * before this, because the node had no way to ask and the resolver no way to\n * receive.\n *\n * Returning `null` still means \"no such workflow\". Return a\n * {@link WorkflowResolutionFailure} to distinguish a version mismatch.\n */\nexport type WorkflowResolver = (\n ref: string,\n version?: number,\n) => Promise<WorkflowResolution> | WorkflowResolution;\n\n/** Narrow a resolver's return value to an explicit failure. */\nexport function isResolutionFailure(value: WorkflowResolution): value is WorkflowResolutionFailure {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"reason\" in value &&\n (value as WorkflowResolutionFailure).reason !== undefined\n );\n}\n\nlet workflowResolver: WorkflowResolver | null = null;\n\n/** Install the host's workflow resolver. Returns an unregister function. */\nexport function registerWorkflowResolver(resolver: WorkflowResolver): () => void {\n workflowResolver = resolver;\n return () => {\n if (workflowResolver === resolver) workflowResolver = null;\n };\n}\n\nexport function getWorkflowResolver(): WorkflowResolver | null {\n return workflowResolver;\n}\n\n// ── Introspection ───────────────────────────────────────────────────────────\n\nexport type CapabilityId = \"llm\" | \"workflow_resolver\" | \"document\";\n\n/**\n * Which capabilities are currently satisfied.\n *\n * Exists so a host (or the CLI, or an agent over MCP) can answer \"what does\n * this graph need that I haven't wired?\" BEFORE a run fails halfway through.\n */\nexport function capabilityStatus(): Record<CapabilityId, boolean> {\n // Imported lazily to avoid dragging the React-dependent rich-input module\n // into the headless engine.\n let documentReady = false;\n try {\n // eslint-disable-next-line @typescript-eslint/no-var-requires, no-undef\n documentReady = Boolean((globalThis as any).__fancyFlowDocumentAdapter);\n } catch {\n documentReady = false;\n }\n return {\n llm: llmClient !== null,\n workflow_resolver: workflowResolver !== null,\n document: documentReady,\n };\n}\n","/**\n * Golden fixtures — the parity guarantee, and a publishing requirement.\n *\n * Every runtime a node package claims runs these same JSON cases. That is what\n * makes \"this node behaves identically on TS and PHP\" verified rather than\n * asserted, and it is the one thing a loose collection of repos can never\n * offer.\n *\n * WHY IT IS REQUIRED RATHER THAN ENCOURAGED: cross-runtime drift does not fail\n * loudly. The 0.9.0 port-resolution divergence produced flows that routed\n * correctly in the editor and silently down one path on the server — status\n * `completed`, no error, no exception, nothing to alert on. A guarantee that\n * only holds when an author opts in is not a guarantee.\n *\n * WHAT A CASE ASSERTS, and why it matters more than it looks:\n *\n * A fixture asserts THE DOWNSTREAM NODE EXECUTED — not the port the node\n * recorded. The distinction is the whole lesson of that incident. A test\n * reading back `outputs.router.__port` stays green while no edge fires and\n * the run halts at the branch: the node faithfully recorded its choice, and\n * nothing downstream ever ran. So the runner wires a real probe to every\n * declared port and reports which probes actually executed.\n *\n * The format is plain JSON with no expressions or callbacks, so the PHP runner\n * executes byte-identical cases without an embedded JS engine.\n */\n\nimport { runFlow } from \"../runtime/run-flow\";\nimport { getNodeKind } from \"../registry/registry\";\nimport { resolveNodePorts } from \"../registry/ports\";\nimport { decodePause, type PauseAwaiting } from \"../registry/pause\";\nimport { registerLlmClient, registerWorkflowResolver } from \"../registry/capabilities\";\nimport type { FlowGraph, FlowNode, NodeExecutor, RunEvent } from \"../types\";\n\n/**\n * Deterministic stand-ins for host capabilities, declared as DATA.\n *\n * `llm_router` cannot reach a provider in CI, so a fixture has to supply a fake\n * `LlmClient`. If the stub format is not shared, each runtime stubs\n * differently and the fixtures stop being comparable — parity theatre. So the\n * fixture declares the stub's *behaviour* and both engines construct it\n * identically from the same JSON.\n */\nexport type FixtureStubs = {\n /** Canned `chooseRoute` answer for the LLM capability. */\n llm_client?: { chooseRoute: { port: string; reason?: string } };\n /** Canned workflow resolution, keyed by ref, for `subflow`. */\n workflow_resolver?: Record<string, FlowGraph | null>;\n};\n\n/** An event a case expects the run to have emitted. */\nexport type FixtureEventExpectation = {\n type: RunEvent[\"type\"];\n /** Emitting node, when it matters. */\n nodeId?: string;\n level?: \"info\" | \"warn\" | \"error\";\n /** Substring match against the message — full text is too brittle to pin. */\n messageContains?: string;\n};\n\n/** What a case expects to have happened. */\nexport type FixtureExpectation = {\n /**\n * Output ports whose downstream node must have executed — the assertion that\n * catches routing drift. Order-insensitive; the set must match exactly, so a\n * node that fires an extra port fails just as loudly as one that fires none.\n */\n ports?: string[];\n /** The value carried downstream, deep-compared when present. */\n value?: unknown;\n /** The run halted for a person. */\n pause?: { awaiting: PauseAwaiting; detail?: unknown };\n /** The run failed, and the message contains this substring. */\n error?: string;\n /**\n * Events the run must have emitted.\n *\n * Emitted events are BEHAVIOUR, not decoration. The hallucinated-port warning\n * is a contract an operator relies on to know a run took the fallback — if\n * one runtime stops emitting it, the guarantee degrades silently. Each entry\n * must match at least one emitted event.\n */\n events?: FixtureEventExpectation[];\n /**\n * The run resumed after a pause and reached this state.\n *\n * Pause/resume is the ONLY path that crosses a persistence boundary, which\n * makes it where two runtimes are most likely to drift — and it had no parity\n * coverage at all while `PausesForHuman` became public API.\n */\n afterResume?: {\n /** Delivered on the paused node's `values` input, as a host would on resume. */\n submit: unknown;\n ports?: string[];\n value?: unknown;\n error?: string;\n };\n};\n\nexport type FixtureCase = {\n /** Human-readable, and what a failure report names. */\n name: string;\n /** Config for the node under test — drives config-derived ports. */\n config?: Record<string, unknown>;\n /**\n * The node's resolved output ports, stated rather than derived.\n *\n * NOT a convenience. TS derives config-driven ports by running a JavaScript\n * function (`switch_case`'s cases, `llm_router`'s routes); PHP cannot, and\n * falls back to the kind's static declaration. Left there, the identical\n * fixture would build a DIFFERENT graph on each runtime — the fixtures would\n * silently stop comparing like with like, which is the exact failure they\n * exist to catch.\n *\n * So a case states its ports the same way an exported document does (see\n * 0.10.1, \"serialize resolved ports\"), and both runners honour it. Omit it\n * only for a node whose ports are static.\n */\n ports?: string[];\n /** Inputs delivered on the node's input ports. */\n inputs?: Record<string, unknown>;\n /**\n * Run this case against an ALIAS or an older config shape.\n *\n * What proves `aliases` and `configVersion` actually work rather than being\n * declared and rotting. A package that renames its kind should have a case\n * pinning that the old id still resolves.\n */\n legacyKind?: string;\n /** Deterministic capability stand-ins for this case. */\n stubs?: FixtureStubs;\n expect: FixtureExpectation;\n};\n\nexport type FixtureFile = {\n /** The kind under test. Must match the manifest's `kind`. */\n kind: string;\n cases: FixtureCase[];\n};\n\nexport type FixtureFailure = {\n case: string;\n message: string;\n};\n\nexport type FixtureRunResult = {\n ok: boolean;\n passed: number;\n failures: FixtureFailure[];\n};\n\nconst SUBJECT = \"subject\";\nconst TRIGGER = \"trigger\";\nconst probeId = (port: string) => `probe:${port}`;\n\n/**\n * Build the graph a case runs in: a trigger, the node under test, and one\n * probe per declared output port.\n *\n * The probes are the point. Reading the subject's return value would tell us\n * what it *recorded*; only a probe tells us what actually reached a downstream\n * node through a real edge.\n */\nfunction buildGraph(kindId: string, testCase: FixtureCase): { graph: FlowGraph; ports: string[] } {\n const subject: FlowNode = {\n id: SUBJECT,\n type: kindId,\n position: { x: 0, y: 100 },\n data: { kind: kindId, config: testCase.config ?? {} },\n } as unknown as FlowNode;\n\n const kind = getNodeKind(kindId) ?? undefined;\n // An explicitly declared port list wins, so both runtimes build the same\n // graph even where one can derive config-driven ports and the other cannot.\n const ports = testCase.ports ?? (resolveNodePorts(subject, kind).outputs ?? []).map((p) => p.id);\n const effective = ports.length ? ports : [\"out\"];\n\n const nodes: FlowNode[] = [\n { id: TRIGGER, type: \"manual_trigger\", position: { x: 0, y: 0 }, data: {} } as unknown as FlowNode,\n subject,\n ...effective.map(\n (port, i) =>\n ({\n id: probeId(port),\n type: \"@particle-academy/transform\",\n position: { x: i * 200, y: 200 },\n data: {},\n }) as unknown as FlowNode,\n ),\n ];\n\n const edges = [\n { id: `e:trigger`, source: TRIGGER, target: SUBJECT },\n ...effective.map((port) => ({\n id: `e:${port}`,\n source: SUBJECT,\n sourceHandle: port,\n target: probeId(port),\n })),\n ];\n\n return { graph: { nodes, edges } as FlowGraph, ports: effective };\n}\n\nfunction deepEqual(a: unknown, b: unknown): boolean {\n return JSON.stringify(a) === JSON.stringify(b);\n}\n\n/**\n * Install the case's capability stubs, returning a function that removes them.\n *\n * Constructed here from the fixture's JSON rather than supplied by the caller,\n * which is the whole point: both runtimes build the same stub from the same\n * data, so a fixture covering `llm_router` compares like with like instead of\n * comparing two different fakes.\n */\nfunction installStubs(stubs: FixtureStubs | undefined): () => void {\n if (!stubs) return () => {};\n\n const teardown: Array<() => void> = [];\n\n if (stubs.llm_client) {\n const answer = stubs.llm_client.chooseRoute;\n teardown.push(registerLlmClient({ chooseRoute: () => ({ ...answer }) }));\n }\n\n if (stubs.workflow_resolver) {\n const table = stubs.workflow_resolver;\n teardown.push(registerWorkflowResolver((ref) => table[ref] ?? null));\n }\n\n return () => teardown.forEach((fn) => fn());\n}\n\nfunction matchesEvent(event: RunEvent, want: FixtureEventExpectation): boolean {\n if (event.type !== want.type) return false;\n\n const e = event as Record<string, unknown>;\n if (want.nodeId !== undefined && e.nodeId !== want.nodeId) return false;\n if (want.level !== undefined && e.level !== want.level) return false;\n if (want.messageContains !== undefined && !String(e.message ?? \"\").includes(want.messageContains)) return false;\n\n return true;\n}\n\n/**\n * Re-run a paused case with a submission delivered, as a durable host would.\n *\n * The submission arrives on `values` because that is the input the builtin\n * human nodes read, and a third-party pausing node that wants fixture coverage\n * should follow the same convention rather than inventing its own.\n */\nasync function resume(\n kindId: string,\n testCase: FixtureCase,\n executor: NodeExecutor,\n pausedNodeId: string,\n submit: unknown,\n): Promise<{ ok: boolean; error?: string; fired: string[]; carried: unknown }> {\n const { graph } = buildGraph(kindId, testCase);\n const fired: string[] = [];\n let carried: unknown;\n\n const executors: Record<string, NodeExecutor> = {\n manual_trigger: () => testCase.inputs ?? {},\n \"@particle-academy/manual_trigger\": () => testCase.inputs ?? {},\n [kindId]: executor,\n };\n\n // The resumed node sees its submission, exactly as the durable runner\n // injects one.\n executors[pausedNodeId] = ((c: Parameters<NodeExecutor>[0]) =>\n executor({ ...c, inputs: { ...(c.inputs as object), values: submit } })) as NodeExecutor;\n\n for (const node of graph.nodes) {\n if (!node.id.startsWith(\"probe:\")) continue;\n const port = node.id.slice(\"probe:\".length);\n executors[node.id] = ((c: { inputs: Record<string, unknown> }) => {\n fired.push(port);\n carried = c.inputs?.in ?? c.inputs;\n return undefined;\n }) as unknown as NodeExecutor;\n }\n\n const releaseStubs = installStubs(testCase.stubs);\n const result = await runFlow(graph, executors, () => {});\n releaseStubs();\n\n return { ok: result.ok, error: result.error, fired, carried };\n}\n\n/**\n * Run one fixture file against a kind's executor.\n *\n * `executor` is the node's own; everything else in the graph is supplied here,\n * so a case exercises the node and nothing but the node.\n */\nexport async function runFixtures(\n file: FixtureFile,\n executor: NodeExecutor,\n): Promise<FixtureRunResult> {\n const failures: FixtureFailure[] = [];\n let passed = 0;\n\n for (const testCase of file.cases) {\n // A case may run against an alias or an older id, which is what proves the\n // package's `aliases` declaration is real rather than decorative.\n const kindId = testCase.legacyKind ?? file.kind;\n const { graph } = buildGraph(kindId, testCase);\n const fired: string[] = [];\n const events: RunEvent[] = [];\n let carried: unknown;\n\n const releaseStubs = installStubs(testCase.stubs);\n\n const executors: Record<string, NodeExecutor> = {\n manual_trigger: () => testCase.inputs ?? {},\n \"@particle-academy/manual_trigger\": () => testCase.inputs ?? {},\n [kindId]: executor,\n };\n\n // A probe per port, bound by NODE ID — `pickExecutor` checks that before\n // kind, so each probe reports which specific port reached it. Recording\n // here, rather than inspecting the subject's result, is what makes this\n // assert reachability instead of intent.\n for (const node of graph.nodes) {\n if (!node.id.startsWith(\"probe:\")) continue;\n const port = node.id.slice(\"probe:\".length);\n executors[node.id] = ((ctx: { inputs: Record<string, unknown> }) => {\n fired.push(port);\n carried = ctx.inputs?.in ?? ctx.inputs;\n return undefined;\n }) as unknown as NodeExecutor;\n }\n\n const result = await runFlow(graph, executors, (e) => events.push(e));\n releaseStubs();\n\n const fail = (message: string) => failures.push({ case: testCase.name, message });\n const expected = testCase.expect;\n let caseOk = true;\n\n if (expected.pause) {\n const paused = decodePause(result.error);\n if (!paused) {\n caseOk = false;\n fail(`expected a pause awaiting \"${expected.pause.awaiting}\", got ${result.ok ? \"a completed run\" : `error: ${result.error}`}`);\n } else {\n if (paused.awaiting !== expected.pause.awaiting) {\n caseOk = false;\n fail(`expected pause awaiting \"${expected.pause.awaiting}\", got \"${paused.awaiting}\"`);\n }\n if (\"detail\" in expected.pause && !deepEqual(paused.detail, expected.pause.detail)) {\n caseOk = false;\n fail(`pause detail mismatch: expected ${JSON.stringify(expected.pause.detail)}, got ${JSON.stringify(paused.detail)}`);\n }\n }\n } else if (expected.error !== undefined) {\n if (result.ok) {\n caseOk = false;\n fail(`expected an error containing \"${expected.error}\", but the run succeeded`);\n } else if (!String(result.error ?? \"\").includes(expected.error)) {\n caseOk = false;\n fail(`expected an error containing \"${expected.error}\", got \"${result.error}\"`);\n }\n } else {\n if (expected.ports !== undefined) {\n const got = [...fired].sort();\n const want = [...expected.ports].sort();\n if (!deepEqual(got, want)) {\n caseOk = false;\n // Name the failure in terms of reachability, because that is what\n // the assertion means and what a reader needs to act on.\n fail(\n `expected these ports to reach a downstream node: [${want.join(\", \")}], but [${got.join(\", \")}] did` +\n (result.ok ? \"\" : ` (run error: ${result.error})`),\n );\n }\n }\n if (\"value\" in expected && !deepEqual(carried, expected.value)) {\n caseOk = false;\n fail(`expected the value carried downstream to be ${JSON.stringify(expected.value)}, got ${JSON.stringify(carried)}`);\n }\n }\n\n // Emitted events are behaviour, not decoration — an operator relies on the\n // hallucinated-port warning to know a run took the fallback.\n for (const want of expected.events ?? []) {\n if (!events.some((e) => matchesEvent(e, want))) {\n caseOk = false;\n fail(`expected an emitted event matching ${JSON.stringify(want)}, but none of the ${events.length} emitted events did`);\n }\n }\n\n // Resume: the only path crossing a persistence boundary, and so the one\n // most likely to drift between runtimes.\n if (expected.afterResume) {\n const paused = decodePause(result.error);\n if (!paused) {\n caseOk = false;\n fail(\"expected the run to pause before resuming, but it never paused\");\n } else {\n const resumed = await resume(kindId, testCase, executor, paused.nodeId, expected.afterResume.submit);\n const want = expected.afterResume;\n\n if (want.error !== undefined) {\n if (resumed.ok || !String(resumed.error ?? \"\").includes(want.error)) {\n caseOk = false;\n fail(`after resume: expected an error containing \"${want.error}\", got ${resumed.ok ? \"success\" : `\"${resumed.error}\"`}`);\n }\n }\n if (want.ports !== undefined) {\n const got = [...resumed.fired].sort();\n const wanted = [...want.ports].sort();\n if (!deepEqual(got, wanted)) {\n caseOk = false;\n fail(`after resume: expected ports [${wanted.join(\", \")}] to reach a downstream node, but [${got.join(\", \")}] did`);\n }\n }\n if (\"value\" in want && !deepEqual(resumed.carried, want.value)) {\n caseOk = false;\n fail(`after resume: expected the value carried downstream to be ${JSON.stringify(want.value)}, got ${JSON.stringify(resumed.carried)}`);\n }\n }\n }\n\n if (caseOk) passed += 1;\n }\n\n return { ok: failures.length === 0, passed, failures };\n}\n\n/**\n * Validate a fixture file's shape before running it.\n *\n * A package that publishes an empty or malformed fixture file has satisfied the\n * letter of the requirement and none of its purpose, so this is checked at\n * publish rather than trusted.\n */\nexport function validateFixtureFile(input: unknown, expectedKind?: string): string[] {\n const problems: string[] = [];\n\n if (typeof input !== \"object\" || input === null || Array.isArray(input)) {\n return [\"Fixture file must be a JSON object.\"];\n }\n\n const f = input as Record<string, unknown>;\n\n if (typeof f.kind !== \"string\" || f.kind.trim() === \"\") {\n problems.push(\"`kind` is required — the kind these cases exercise.\");\n } else if (expectedKind && f.kind !== expectedKind) {\n problems.push(`\\`kind\\` is \"${f.kind}\" but the manifest declares \"${expectedKind}\".`);\n }\n\n if (!Array.isArray(f.cases) || f.cases.length === 0) {\n problems.push(\"`cases` must contain at least one case — an empty fixture file proves nothing.\");\n return problems;\n }\n\n // At least one case must exercise a failure.\n //\n // \"Does it fail the same way\" deserves equal weight to \"does it succeed the\n // same way\": the incident that motivated this whole mechanism was a FAILURE\n // that reported `completed` with no error. A suite that only covers happy\n // paths cannot catch a runtime that fails differently — or does not fail\n // at all.\n const coversFailure = f.cases.some((c: unknown) => {\n const expect = (c as { expect?: Record<string, unknown> })?.expect;\n return Boolean(expect && (\"error\" in expect || \"pause\" in expect));\n });\n if (!coversFailure) {\n problems.push(\n \"At least one case must assert a failure (`expect.error`) or a pause (`expect.pause`). Every case here covers a success path, and the divergence this format exists to catch reported success while doing nothing.\",\n );\n }\n\n f.cases.forEach((c: unknown, i: number) => {\n const label = `cases[${i}]`;\n if (typeof c !== \"object\" || c === null) {\n problems.push(`${label} must be an object.`);\n return;\n }\n const testCase = c as Record<string, unknown>;\n if (typeof testCase.name !== \"string\" || testCase.name.trim() === \"\") {\n problems.push(`${label}.name is required — a failure report names it.`);\n }\n if (typeof testCase.expect !== \"object\" || testCase.expect === null) {\n problems.push(`${label}.expect is required — a case that asserts nothing passes vacuously.`);\n return;\n }\n const expect = testCase.expect as Record<string, unknown>;\n if (\n expect.ports === undefined &&\n expect.value === undefined &&\n expect.pause === undefined &&\n expect.error === undefined\n ) {\n problems.push(`${label}.expect must assert at least one of: ports, value, pause, error.`);\n }\n if (expect.ports !== undefined && (!Array.isArray(expect.ports) || expect.ports.some((p) => typeof p !== \"string\"))) {\n problems.push(`${label}.expect.ports must be an array of port id strings.`);\n }\n });\n\n return problems;\n}\n"]}
1
+ {"version":3,"sources":["../src/registry/registry.ts","../src/registry/ports.ts","../src/runtime/run-flow.ts","../src/registry/pause.ts","../src/marketplace/manifest.ts","../src/registry/capabilities.ts","../src/marketplace/fixtures.ts"],"names":["aliases"],"mappings":"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","file":"engine.cjs","sourcesContent":["import type { ConfigField, NodeKindDefinition } from \"./types\";\n\nconst kinds = new Map<string, NodeKindDefinition<any, any, any>>();\n/** alias → canonical name. See `resolveKindId`. */\nconst aliases = new Map<string, string>();\nconst listeners = new Set<() => void>();\n\n/**\n * registerNodeKind — install a node kind in the global registry. Returns\n * an `unregister` function. Calling with the same name replaces the prior\n * registration (handy for HMR).\n *\n * A kind's `name` is its CANONICAL id and is what gets written into saved\n * documents. Publish namespaced (`@fancy/llm_branch`, `@acme/salesforce_upsert`)\n * and list any previous bare names in `aliases`, so graphs saved before the\n * rename keep resolving.\n */\nexport function registerNodeKind<TC = any, TI = any, TO = any>(\n definition: NodeKindDefinition<TC, TI, TO>,\n): () => void {\n kinds.set(definition.name, definition as NodeKindDefinition<any, any, any>);\n for (const alias of definition.aliases ?? []) aliases.set(alias, definition.name);\n notify();\n return () => {\n if (kinds.get(definition.name) === (definition as any)) {\n kinds.delete(definition.name);\n for (const alias of definition.aliases ?? []) {\n if (aliases.get(alias) === definition.name) aliases.delete(alias);\n }\n notify();\n }\n };\n}\n\n/**\n * Resolve any id — canonical or alias — to the canonical one, or null.\n *\n * `kind` is persisted inside every saved graph, so a bare name that two\n * packages could both claim is unfixable after the fact: the ambiguous string\n * is already in the document. Canonical ids are namespaced; aliases exist so\n * documents written before namespacing keep opening.\n */\nexport function resolveKindId(id: string): string | null {\n if (kinds.has(id)) return id;\n const canonical = aliases.get(id);\n return canonical && kinds.has(canonical) ? canonical : null;\n}\n\n/** Get a single kind by canonical id or alias, or null. */\nexport function getNodeKind(name: string): NodeKindDefinition | null {\n const canonical = resolveKindId(name);\n return canonical ? ((kinds.get(canonical) as NodeKindDefinition) ?? null) : null;\n}\n\n/** Every id a kind answers to — canonical first. Used to key node-type maps. */\nexport function kindIds(kind: NodeKindDefinition): string[] {\n return [kind.name, ...(kind.aliases ?? [])];\n}\n\n/** List every registered kind, optionally filtered by category. */\nexport function listNodeKinds(category?: string): NodeKindDefinition[] {\n const all = Array.from(kinds.values()) as NodeKindDefinition[];\n return category ? all.filter((k) => k.category === category) : all;\n}\n\n/** Subscribe to registry changes. Returns an unsubscribe function. */\nexport function onNodeKindsChanged(listener: () => void): () => void {\n listeners.add(listener);\n return () => listeners.delete(listener);\n}\n\nfunction notify(): void {\n for (const l of listeners) l();\n}\n\n/** Fill in defaults from a kind's configSchema for newly-created nodes. */\nexport function defaultConfigFor(kind: NodeKindDefinition): Record<string, unknown> {\n const fromKind = kind.defaultConfig ? { ...(kind.defaultConfig as Record<string, unknown>) } : {};\n for (const field of kind.configSchema ?? []) {\n if (fromKind[field.key] !== undefined) continue;\n if (\"default\" in field && (field as any).default !== undefined) {\n fromKind[field.key] = (field as any).default;\n }\n }\n return fromKind;\n}\n\n/**\n * Validate a config object against a kind's schema. Returns an array of\n * issues (empty = valid). Validation is intentionally light — type\n * coercion + required-field checks. Hosts can layer Zod / Ajv on top.\n */\nexport function validateConfig(\n kind: NodeKindDefinition,\n config: Record<string, unknown>,\n): Array<{ key: string; message: string }> {\n const issues: Array<{ key: string; message: string }> = [];\n for (const field of kind.configSchema ?? []) {\n const value = config[field.key];\n if (field.required && (value === undefined || value === null || value === \"\")) {\n issues.push({ key: field.key, message: `${field.label} is required` });\n continue;\n }\n if (value === undefined || value === null) continue;\n const issue = validateField(field, value);\n if (issue) issues.push({ key: field.key, message: issue });\n }\n return issues;\n}\n\nfunction validateField(field: ConfigField, value: unknown): string | null {\n switch (field.type) {\n case \"text\":\n case \"textarea\":\n case \"expression\":\n case \"credential\":\n return typeof value === \"string\" ? null : `${field.label} must be a string`;\n case \"number\": {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return `${field.label} must be a number`;\n if (field.min !== undefined && value < field.min) return `${field.label} must be >= ${field.min}`;\n if (field.max !== undefined && value > field.max) return `${field.label} must be <= ${field.max}`;\n return null;\n }\n case \"switch\":\n return typeof value === \"boolean\" ? null : `${field.label} must be a boolean`;\n case \"select\": {\n const allowed = field.options.map((o) => o.value);\n return allowed.includes(String(value)) ? null : `${field.label} must be one of ${allowed.join(\", \")}`;\n }\n case \"json\":\n return null; // permissive — just JSON-shaped\n case \"repeater\": {\n if (!Array.isArray(value)) return `${field.label} must be a list`;\n if (field.minItems !== undefined && value.length < field.minItems) {\n return `${field.label} needs at least ${field.minItems}`;\n }\n if (field.maxItems !== undefined && value.length > field.maxItems) {\n return `${field.label} allows at most ${field.maxItems}`;\n }\n // Surface the first offending row so the author knows WHICH one.\n for (let i = 0; i < value.length; i++) {\n const row = value[i];\n if (!row || typeof row !== \"object\" || Array.isArray(row)) {\n return `${field.label} item ${i + 1} must be an object`;\n }\n for (const sub of field.fields) {\n const cell = (row as Record<string, unknown>)[sub.key];\n if (sub.required && (cell === undefined || cell === null || cell === \"\")) {\n return `${field.label} item ${i + 1}: ${sub.label} is required`;\n }\n if (cell === undefined || cell === null) continue;\n const issue = validateField(sub, cell);\n if (issue) return `${field.label} item ${i + 1}: ${issue}`;\n }\n }\n return null;\n }\n case \"keyvalue\": {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return `${field.label} must be a key/value map`;\n }\n const allowed = field.valueOptions?.map((o) => o.value);\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n if (typeof v !== \"string\") return `${field.label}: \"${k}\" must be a string`;\n if (allowed && !allowed.includes(v)) {\n return `${field.label}: \"${k}\" must be one of ${allowed.join(\", \")}`;\n }\n }\n return null;\n }\n case \"document\":\n return null; // opaque to fancy-flow — the host's editor owns its shape\n default:\n return null;\n }\n}\n\n/** Default accents per category. */\nexport function categoryAccent(category: string): string {\n switch (category) {\n case \"trigger\": return \"#10b981\";\n case \"logic\": return \"#f59e0b\";\n case \"data\": return \"#0ea5e9\";\n case \"ai\": return \"#8b5cf6\";\n case \"io\": return \"#3b82f6\";\n case \"human\": return \"#ec4899\";\n case \"output\": return \"#a855f7\";\n case \"layout\": return \"#64748b\";\n default: return \"#71717a\";\n }\n}\n","import type { FlowNode, PortDescriptor } from \"../types\";\nimport type { NodeKindDefinition, PortSpec } from \"./types\";\n\n/**\n * Port resolution — the single place a node's ports are derived, shared by\n * the canvas renderer and the headless runtime.\n *\n * This module is deliberately React-free: `runFlow` (the `/engine` entry)\n * imports it, and the engine bundle must stay free of React.\n *\n * ## Why this is centralized\n *\n * Ports used to be read in two places that disagreed — the canvas consulted\n * `data.outputs ?? kind.outputs`, while the runtime consulted `data.outputs`\n * ONLY and fell back to a single `out` port. A kind that declared branch ports\n * therefore drew correctly and then routed as if it had one output, unless the\n * host remembered to mirror the ports onto every node's `data`. Both callers\n * now go through `resolveNodePorts`, so declared ports and executed ports\n * cannot drift apart.\n */\n\n/**\n * Resolve a `PortSpec` against a config object.\n *\n * A config-driven spec is author-supplied and runs on every render, so a throw\n * is contained: it degrades to \"undeclared\" (letting the caller fall back)\n * rather than taking out the canvas or aborting a run mid-flight.\n */\nexport function resolvePortSpec<TConfig>(\n spec: PortSpec<TConfig> | undefined,\n config: TConfig,\n): PortDescriptor[] | undefined {\n if (spec === undefined) return undefined;\n if (typeof spec !== \"function\") return spec;\n try {\n const resolved = (spec as (c: TConfig) => PortDescriptor[])(config);\n return Array.isArray(resolved) ? resolved : undefined;\n } catch {\n return undefined;\n }\n}\n\n/** Read the config bag off a node, tolerating the FlowNodeData union. */\nexport function nodeConfig(node: Pick<FlowNode, \"data\">): Record<string, unknown> {\n return ((node.data as any)?.config ?? {}) as Record<string, unknown>;\n}\n\n/**\n * Resolve a node's effective ports.\n *\n * Precedence: explicit `data.inputs`/`data.outputs` (a per-node host override)\n * beats the kind's declaration. `undefined` means \"nothing declared\" — the\n * caller applies its own category default.\n */\nexport function resolveNodePorts(\n node: Pick<FlowNode, \"data\">,\n kind?: Pick<NodeKindDefinition<any>, \"inputs\" | \"outputs\">,\n): { inputs?: PortDescriptor[]; outputs?: PortDescriptor[] } {\n const config = nodeConfig(node);\n const data = node.data as any;\n return {\n inputs: data?.inputs ?? resolvePortSpec(kind?.inputs, config),\n outputs: data?.outputs ?? resolvePortSpec(kind?.outputs, config),\n };\n}\n","import type {\n ExecutorRegistry,\n FlowEdge,\n FlowGraph,\n FlowNode,\n NodeExecutor,\n RunEvent,\n} from \"../types\";\n// Both modules are React-free by design — the `/engine` entry must not pull in\n// React. Import them directly rather than via the `registry` barrel, which\n// re-exports the RegistryNode component.\nimport { getNodeKind, kindIds } from \"../registry/registry\";\nimport { resolveNodePorts } from \"../registry/ports\";\n\nexport type RunOptions = {\n /** Stop the run after this many ms. Default: no timeout. */\n timeoutMs?: number;\n /** Abort signal — host can cancel the run. */\n signal?: AbortSignal;\n /** Initial inputs supplied to entry-point nodes (no incoming edges). */\n initialInputs?: Record<string, Record<string, unknown>>;\n /** Nesting depth — set by `subflow` when it runs a child graph. */\n depth?: number;\n};\n\nexport type RunResult = {\n ok: boolean;\n /** Outputs collected per node, keyed by node id. */\n outputs: Record<string, unknown>;\n /** Error captured if any node threw. */\n error?: string;\n};\n\n/**\n * runFlow — topological execution of a FlowGraph against an ExecutorRegistry.\n *\n * Each node runs once, when all upstream nodes have produced outputs on the\n * connected ports. Decision nodes (or any executor that returns `{ branch:\n * 'true' }`) can short-circuit specific output ports — only edges leaving\n * an \"active\" port propagate to downstream nodes.\n *\n * Cycles are detected and abort the run with an error.\n *\n * The `onEvent` callback receives a stream of `RunEvent`s — wire it to a\n * status feed, log panel, or store.\n */\nexport async function runFlow(\n graph: FlowGraph,\n executors: ExecutorRegistry,\n onEvent: (event: RunEvent) => void = () => {},\n options: RunOptions = {},\n): Promise<RunResult> {\n const { signal, initialInputs = {}, timeoutMs, depth = 0 } = options;\n const outputs: Record<string, unknown> = {};\n const portValues = new Map<string, unknown>(); // key: `${nodeId}:${portId}`\n const completed = new Set<string>();\n const errors: string[] = [];\n\n // Topological order via Kahn's algorithm. We allow nodes to run as soon\n // as their incoming edges' source ports have produced values, so the\n // order here is just a deterministic baseline used for cycle detection.\n const order = topoSort(graph);\n if (order === null) {\n const msg = \"Cycle detected in flow graph — aborting.\";\n onEvent({ type: \"run-error\", error: msg });\n return { ok: false, outputs, error: msg };\n }\n\n const incomingByNode = indexIncoming(graph.edges);\n const timer = timeoutMs ? setTimeout(() => errors.push(`Run timed out after ${timeoutMs}ms`), timeoutMs) : null;\n\n onEvent({ type: \"run-start\" });\n\n try {\n for (const node of order) {\n if (signal?.aborted) throw new Error(\"aborted\");\n if (errors.length) break;\n\n const incoming = incomingByNode.get(node.id) ?? [];\n\n // Run a node once any upstream branch reaches it. We iterate in\n // topological order, so by the time we reach this node every upstream\n // node has been processed — each incoming edge is therefore *settled*\n // (active or dead, never still-pending). Requiring ALL incoming edges to\n // be active wrongly skipped MERGE POINTS: when a Decision routes down one\n // branch, the other branch's edge stays dead forever, so an `every` check\n // skipped the shared continuation node and halted the run after the first\n // branch (#1). Run when AT LEAST ONE incoming edge is active —\n // collectInputs() only reads from the active ones. A genuine parallel\n // join still works: in topo order both of its inputs are already active.\n if (incoming.length > 0) {\n const anyActive = incoming.some((e) => portValues.has(`${e.source}:${e.sourceHandle ?? \"out\"}`));\n if (!anyActive) {\n onEvent({ type: \"node-status\", nodeId: node.id, status: \"idle\", text: \"skipped\" });\n continue;\n }\n }\n\n // Note + layout (lane/pool) nodes are visual only — never executed. Edges\n // cross lanes freely, so grouping never affects topology.\n const visualKind = getNodeKind(node.type ?? \"\");\n if (node.type === \"note\" || visualKind?.category === \"layout\") {\n onEvent({\n type: \"node-status\",\n nodeId: node.id,\n status: \"idle\",\n text: visualKind?.category === \"layout\" ? \"lane\" : \"annotation\",\n });\n continue;\n }\n\n onEvent({ type: \"node-status\", nodeId: node.id, status: \"running\" });\n\n const inputs = collectInputs(node, incoming, portValues, initialInputs);\n const exec = pickExecutor(executors, node);\n if (!exec) {\n const msg = `No executor registered for kind=${node.type}`;\n errors.push(msg);\n onEvent({ type: \"node-status\", nodeId: node.id, status: \"error\", text: msg });\n onEvent({ type: \"log\", nodeId: node.id, level: \"error\", message: msg });\n break;\n }\n\n try {\n const result = await Promise.resolve(\n exec({\n node,\n inputs,\n abort: (reason) => { throw new Error(reason ?? \"aborted\"); },\n emit: onEvent,\n depth,\n }),\n );\n outputs[node.id] = result;\n\n // Decide which output ports were activated. Three conventions:\n // 1) If result is `{ __port: \"out\", value: x }`, only that port emits.\n // 2) If result has `branch: <portId>`, only that port emits (decision sugar).\n // 3) Otherwise, the value is published on every declared output port.\n const activated = activatedPorts(node, result);\n for (const portId of activated.ports) {\n portValues.set(`${node.id}:${portId}`, activated.value);\n onEvent({ type: \"node-output\", nodeId: node.id, portId, value: activated.value });\n }\n completed.add(node.id);\n onEvent({ type: \"node-status\", nodeId: node.id, status: \"done\" });\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n errors.push(msg);\n onEvent({ type: \"node-status\", nodeId: node.id, status: \"error\", text: msg });\n onEvent({ type: \"log\", nodeId: node.id, level: \"error\", message: msg });\n break;\n }\n }\n } finally {\n if (timer) clearTimeout(timer);\n }\n\n const ok = errors.length === 0;\n onEvent({ type: \"run-end\", ok });\n return ok ? { ok, outputs } : { ok, outputs, error: errors[0] };\n}\n\nfunction indexIncoming(edges: FlowEdge[]): Map<string, FlowEdge[]> {\n const map = new Map<string, FlowEdge[]>();\n for (const e of edges) {\n const list = map.get(e.target) ?? [];\n list.push(e);\n map.set(e.target, list);\n }\n return map;\n}\n\nfunction topoSort(graph: FlowGraph): FlowNode[] | null {\n const inDegree = new Map<string, number>();\n for (const n of graph.nodes) inDegree.set(n.id, 0);\n for (const e of graph.edges) inDegree.set(e.target, (inDegree.get(e.target) ?? 0) + 1);\n const queue: string[] = [];\n for (const [id, d] of inDegree) if (d === 0) queue.push(id);\n const ordered: string[] = [];\n while (queue.length) {\n const id = queue.shift()!;\n ordered.push(id);\n for (const e of graph.edges) {\n if (e.source !== id) continue;\n const next = (inDegree.get(e.target) ?? 0) - 1;\n inDegree.set(e.target, next);\n if (next === 0) queue.push(e.target);\n }\n }\n if (ordered.length !== graph.nodes.length) return null;\n const byId = new Map(graph.nodes.map((n) => [n.id, n]));\n return ordered.map((id) => byId.get(id)!).filter(Boolean);\n}\n\nfunction collectInputs(\n node: FlowNode,\n incoming: FlowEdge[],\n portValues: Map<string, unknown>,\n initial: Record<string, Record<string, unknown>>,\n): Record<string, unknown> {\n const inputs: Record<string, unknown> = { ...(initial[node.id] ?? {}) };\n for (const e of incoming) {\n const portId = e.targetHandle ?? \"in\";\n const val = portValues.get(`${e.source}:${e.sourceHandle ?? \"out\"}`);\n inputs[portId] = val;\n }\n return inputs;\n}\n\nfunction pickExecutor(\n executors: ExecutorRegistry,\n node: FlowNode,\n): NodeExecutor | undefined {\n if (executors[node.id]) return executors[node.id];\n if (node.type && executors[node.type]) return executors[node.type];\n\n // Try every id the kind answers to. Kinds are namespaced (`@fancy/switch_case`)\n // while a host may have bound its executor under the bare name it used before\n // — or vice versa. Without this, the rename would silently stop matching and\n // the node would fall through to `*` or simply not run: a breaking change\n // wearing the costume of a rename.\n const kind = node.type ? getNodeKind(node.type) : null;\n if (kind) {\n for (const id of kindIds(kind)) {\n if (executors[id]) return executors[id];\n }\n }\n\n return executors[\"*\"];\n}\n\nfunction activatedPorts(node: FlowNode, result: unknown): { ports: string[]; value: unknown } {\n if (result && typeof result === \"object\") {\n const r = result as Record<string, unknown>;\n if (typeof r.__port === \"string\") {\n return { ports: [r.__port], value: r.value };\n }\n if (typeof r.branch === \"string\") {\n return { ports: [r.branch], value: r.value ?? r };\n }\n }\n // Resolve through the shared helper so the ports the runtime activates are\n // the same ones the canvas drew — including config-driven ports, which the\n // node's `data` does not carry. Falls back to a lone `out` when a node\n // declares nothing.\n const kind = getNodeKind((node.data as any)?.kind ?? node.type ?? \"\") ?? undefined;\n const declared = resolveNodePorts(node, kind).outputs?.map((p) => p.id);\n return { ports: declared?.length ? declared : [\"out\"], value: result };\n}\n","/**\n * The human-pause contract.\n *\n * A workflow that waits for a person is not an error, but it travels the same\n * channel as one: the executor aborts, the engine records a reason string, and\n * the durable runner decides whether that string meant \"failed\" or \"waiting\".\n *\n * That seam existed before this module, as two `str_starts_with` checks in the\n * Laravel run job against constants owned by two BUILTIN executors. It worked,\n * and it was invisible: a third-party human-input node had no way to announce\n * that it pauses, and nothing stopped a refactor from removing the mechanism\n * out from under published packages. Reported by the MOIC Suite consumer, who\n * needed exactly that and had to reach for a private constant to get it.\n *\n * So the encoding is now public, typed, and versioned by prefix rather than\n * implied. The wire format stays a plain string on purpose — it survives the\n * existing abort → `RunResult.error` path unchanged, crosses a queue boundary,\n * and decodes identically in PHP, none of which a thrown class would do.\n *\n * @see decodePause — the one function a durable runner needs.\n */\n\n/**\n * What the run is waiting for.\n *\n * `approval` and `input` are the shapes both runtimes ship. The type stays open\n * because the whole point is that a marketplace node can define its own —\n * a signature step, a payment confirmation, a review queue — and a runner that\n * does not recognise one should report it rather than guess.\n */\nexport type PauseAwaiting = \"approval\" | \"input\" | (string & {});\n\n/** A run halted, waiting for a person. */\nexport type PauseSignal = {\n /** The node that paused — where a submission gets injected on resume. */\n nodeId: string;\n awaiting: PauseAwaiting;\n /**\n * Kind-supplied context for whoever renders the wait — a form schema, the\n * question being asked, a diff to approve. Must be JSON-serializable: it\n * crosses a queue boundary and, for durable runs, a database column.\n */\n detail?: unknown;\n};\n\n/** Marks a reason string as a pause rather than a failure. */\nexport const PAUSE_PREFIX = \"fancy-flow:pause:\";\n\n/**\n * Reason prefixes shipped before this contract, kept decodable forever.\n *\n * These are what `DurableApprovalExecutor` and `DurableUserInputExecutor`\n * emitted, and they are written into the `error` column of every run that\n * paused under an older version. Dropping them would strand those runs\n * mid-flight — a resume path that only works for new runs is not a resume path.\n */\nexport const LEGACY_PAUSE_PREFIXES: ReadonlyArray<readonly [string, PauseAwaiting]> = [\n [\"awaiting-approval:\", \"approval\"],\n [\"awaiting-input:\", \"input\"],\n];\n\n/**\n * Encode a pause as the reason string an executor aborts with.\n *\n * The payload is JSON rather than delimited fields because a node id may\n * contain a colon, and a positional encoding that breaks on user data is the\n * kind of bug that only shows up in someone else's graph.\n */\nexport function encodePause(signal: PauseSignal): string {\n const { nodeId, awaiting, detail } = signal;\n return PAUSE_PREFIX + JSON.stringify(detail === undefined ? { nodeId, awaiting } : { nodeId, awaiting, detail });\n}\n\n/**\n * Decode a run's error reason into a pause, or null if it was a real failure.\n *\n * This is the whole contract from a runner's side: call it on `result.error`,\n * and if it returns non-null, persist the run as waiting on `signal.nodeId`\n * instead of failing it. Accepts the legacy prefixes, so a runner written\n * against this handles runs that paused under an older version.\n */\nexport function decodePause(reason: string | null | undefined): PauseSignal | null {\n if (typeof reason !== \"string\") return null;\n\n if (reason.startsWith(PAUSE_PREFIX)) {\n const body = reason.slice(PAUSE_PREFIX.length);\n try {\n const parsed = JSON.parse(body) as Partial<PauseSignal>;\n // A malformed payload is a corrupt pause, not a failure to report as a\n // crash — but it is also not something to invent a node id for.\n if (typeof parsed?.nodeId !== \"string\" || typeof parsed?.awaiting !== \"string\") return null;\n return \"detail\" in parsed\n ? { nodeId: parsed.nodeId, awaiting: parsed.awaiting, detail: parsed.detail }\n : { nodeId: parsed.nodeId, awaiting: parsed.awaiting };\n } catch {\n return null;\n }\n }\n\n for (const [prefix, awaiting] of LEGACY_PAUSE_PREFIXES) {\n if (reason.startsWith(prefix)) {\n return { nodeId: reason.slice(prefix.length), awaiting };\n }\n }\n\n return null;\n}\n\n/** True when a run's error reason is actually a pause. */\nexport function isPause(reason: string | null | undefined): boolean {\n return decodePause(reason) !== null;\n}\n\n/**\n * Abort the current node as a pause.\n *\n * Called from inside an executor with its own context. Node authors should\n * reach for this rather than hand-encoding a reason, so the format stays ours\n * to change:\n *\n * ```ts\n * const values = ctx.inputs.values;\n * if (values === undefined) pauseForHuman(ctx, \"input\", { fields });\n * return values;\n * ```\n *\n * Note the `undefined` check — an empty submission (`{}`) is a real answer and\n * must resume. Truthiness here pauses forever on an empty form.\n */\nexport function pauseForHuman(\n ctx: { node: { id: string }; abort: (reason?: string) => never },\n awaiting: PauseAwaiting,\n detail?: unknown,\n): never {\n return ctx.abort(encodePause({ nodeId: ctx.node.id, awaiting, detail }));\n}\n","/**\n * The node package manifest — what a marketplace node declares about itself.\n *\n * A node is not one artifact. It is a kind definition (palette entry, config\n * schema, ports, renderer) plus an executor for EACH runtime the consumer runs.\n * A package shipping only a TS executor is unusable to anyone executing on PHP,\n * and without a manifest that is invisible until a run fails. Requested by the\n * MOIC Suite consumer (fancy-flow#2 §2), who runs the editor in TS and executes\n * in PHP and hit exactly this.\n *\n * The manifest is data, not code: the registry, the CLI, and the MCP all read\n * it without executing anything a package author wrote.\n *\n * ## Why the engine range lives per runtime\n *\n * The first cut of this manifest carried ONE `fancyFlow` range, and it was\n * wrong: the two engines version independently, so a single range cannot say\n * \"needs npm >=0.11 AND php >=0.5\". A package supporting both runtimes would\n * install cleanly against a host whose OTHER runtime was too old — the 0.9.0\n * failure shape wearing a manifest. The range belongs inside each runtime.\n */\n\nimport type { PauseAwaiting } from \"../registry/pause\";\n\n/** The current manifest schema version. Bump only on a breaking shape change. */\nexport const NODE_MANIFEST_SCHEMA_VERSION = 1;\n\n/**\n * A runtime a node can implement.\n *\n * Open rather than a closed union — the PHP and Node twins are what exist\n * today, but the point of a manifest is that a runtime we haven't written can\n * declare itself without a release here.\n */\nexport type NodeRuntimeId = \"ts\" | \"php\" | (string & {});\n\n/**\n * How one runtime provides this node, and which engine version it needs.\n *\n * `entry` and `package` are both here because the two ecosystems install\n * differently — a module path within the package for TS, a Composer\n * requirement for PHP — and pretending otherwise just moves the problem into\n * the CLI. Exactly one is required.\n */\nexport type NodeRuntimeSpec = {\n /** Module path within the package (TS-style runtimes). */\n entry?: string;\n /** Dependency requirement resolved by that ecosystem (PHP/Composer-style). */\n package?: string;\n /** Semver range of THIS runtime's engine. Required — see the module note. */\n engine: string;\n};\n\n/**\n * Whether a capability must be wired for the node to work at all.\n *\n * `required` is checked at AUTHOR time, not run time. The failure that hurts is\n * a node that installs fine, authors fine, and silently no-ops during a run —\n * the same silence as a routing bug. An editor can grey the node and say which\n * capability the host never registered.\n */\nexport type CapabilityRequirement = \"required\" | \"optional\";\n\n/**\n * Whether a node is safe to run again.\n *\n * Durable runs RETRY. A node that writes needs to say so, or a host has to pick\n * one retry policy for every node and get it wrong somewhere.\n */\nexport type SideEffects = \"none\" | \"idempotent\" | \"unsafe-to-replay\";\n\nexport type NodePackageManifest = {\n /** Must equal `NODE_MANIFEST_SCHEMA_VERSION`. */\n schemaVersion: number;\n /** Package name, as installed (`@acme/fancy-flow-salesforce`). */\n name: string;\n /**\n * The canonical kind id this package provides — namespaced, and the string\n * that gets persisted into every document using it.\n */\n kind: string;\n /**\n * Previous ids this kind still answers to.\n *\n * Core renamed `llm_branch` to `llm_router` and kept every old id working.\n * Third-party packages will rename too, and their documents break the same\n * way core's would have — so packages get the same escape hatch, otherwise\n * only first-party nodes can rename safely.\n */\n aliases?: string[];\n /**\n * Version of this node's CONFIG shape, independent of the document schema.\n *\n * A node's config evolves on its own clock. Without a declared version, every\n * executor accretes hand-written read-fallbacks forever (MOIC carries one for\n * `routes[].key` → `routes[].port`), because nothing canonicalises old config\n * the way import canonicalises kind ids.\n */\n configVersion?: number;\n /** Per-runtime entrypoints and engine ranges. */\n runtimes: Partial<Record<NodeRuntimeId, NodeRuntimeSpec>>;\n /**\n * Host capabilities this node needs, and whether each is mandatory.\n *\n * Declared so the CLI and the editor can say what to wire BEFORE a run,\n * rather than the node silently no-opping or crashing mid-run.\n */\n capabilities?: Record<string, CapabilityRequirement>;\n /**\n * Path to this node's golden fixtures, relative to the package root.\n *\n * REQUIRED. Every runtime the package claims runs these same cases, which is\n * what makes \"behaves identically on both runtimes\" verified rather than\n * asserted. See `./fixtures`.\n */\n fixtures: string;\n /**\n * Declares the node halts for a person. Mirrors `NodeKindDefinition`.\n *\n * A host-planning fact, not a node internal: a parent that embeds workflows\n * needs to reject a child that can pause, because a paused child wedges the\n * parent — and discovering that at run time means watching a run park.\n */\n pausesForHuman?: PauseAwaiting;\n /** Whether this node is safe to replay. See `SideEffects`. */\n sideEffects?: SideEffects;\n /** One-line summary — what `search_nodes` matches against. */\n description?: string;\n /**\n * Assigned by the registry, never by the author. Present in a manifest being\n * submitted for publication, it is a claim to a trust signal the author does\n * not get to make.\n */\n verified?: boolean;\n};\n\nexport type ManifestProblem = {\n level: \"error\" | \"warning\";\n field: string;\n message: string;\n};\n\nexport type ManifestValidation = {\n /** True when there are no `error`-level problems. Warnings do not block. */\n ok: boolean;\n manifest?: NodePackageManifest;\n problems: ManifestProblem[];\n};\n\n/** Reserved for first-party packages; the registry rejects other claimants. */\nconst FIRST_PARTY_SCOPE = \"@particle-academy/\";\n\n/** `@scope/name` — the shape 0.11.0 made canonical for kind ids. */\nconst NAMESPACED_KIND = /^@[a-z0-9][a-z0-9._-]*\\/[a-z0-9][a-z0-9._-]*$/i;\n\nconst SIDE_EFFECTS: readonly string[] = [\"none\", \"idempotent\", \"unsafe-to-replay\"];\nconst REQUIREMENTS: readonly string[] = [\"required\", \"optional\"];\n\nfunction err(field: string, message: string): ManifestProblem {\n return { level: \"error\", field, message };\n}\n\nfunction warn(field: string, message: string): ManifestProblem {\n return { level: \"warning\", field, message };\n}\n\n/**\n * Validate a manifest read from disk or a registry.\n *\n * Returns every problem rather than throwing on the first, because an author\n * fixing a package wants the whole list — a validator that reveals one error\n * per run turns a five-minute fix into five round trips.\n */\nexport function validateNodeManifest(input: unknown): ManifestValidation {\n const problems: ManifestProblem[] = [];\n\n if (typeof input !== \"object\" || input === null || Array.isArray(input)) {\n return { ok: false, problems: [err(\"\", \"Manifest must be a JSON object.\")] };\n }\n\n const m = input as Record<string, unknown>;\n\n // Version first: an unknown version means every other check below is\n // guessing at a shape we do not know, so say so plainly instead of\n // half-reading it and reporting confident nonsense about the rest.\n if (m.schemaVersion !== NODE_MANIFEST_SCHEMA_VERSION) {\n if (typeof m.schemaVersion !== \"number\") {\n problems.push(err(\"schemaVersion\", `Required, and must be ${NODE_MANIFEST_SCHEMA_VERSION}.`));\n } else {\n return {\n ok: false,\n problems: [\n err(\n \"schemaVersion\",\n `Unsupported manifest version ${m.schemaVersion}; this fancy-flow understands ${NODE_MANIFEST_SCHEMA_VERSION}. Upgrade fancy-flow to install this node.`,\n ),\n ],\n };\n }\n }\n\n if (typeof m.name !== \"string\" || m.name.trim() === \"\") {\n problems.push(err(\"name\", \"Required — the package name as installed.\"));\n }\n\n validateKind(m.kind, problems);\n validateAliases(m.aliases, problems);\n\n if (m.configVersion !== undefined && (typeof m.configVersion !== \"number\" || !Number.isInteger(m.configVersion))) {\n problems.push(err(\"configVersion\", \"Must be an integer.\"));\n }\n\n // A leftover single range from the pre-per-runtime shape. Worth naming\n // explicitly rather than ignoring — it silently means \"no engine constraint\".\n if (m.fancyFlow !== undefined) {\n problems.push(\n err(\n \"fancyFlow\",\n \"A single engine range cannot express the split — it cannot say \\\"needs ts >=0.15 AND php >=0.7\\\". Move the range into each entry of `runtimes` as `engine`.\",\n ),\n );\n }\n\n validateRuntimes(m.runtimes, problems);\n\n // Fixtures: the publish gate. Cross-runtime drift does not fail loudly —\n // it completes, down one path, with no error — so it has to be caught by\n // something that runs, not by review.\n if (typeof m.fixtures !== \"string\" || m.fixtures.trim() === \"\") {\n problems.push(\n err(\"fixtures\", \"Required — path to the node's golden fixtures. Every claimed runtime runs them, which is what makes cross-runtime parity verified rather than claimed.\"),\n );\n }\n\n validateCapabilities(m.capabilities, problems);\n\n if (m.sideEffects !== undefined && !SIDE_EFFECTS.includes(m.sideEffects as string)) {\n problems.push(err(\"sideEffects\", `Must be one of: ${SIDE_EFFECTS.join(\", \")}.`));\n }\n\n if (m.verified !== undefined) {\n problems.push(\n err(\"verified\", \"Assigned by the registry, not the package. Remove it — a package cannot vouch for itself.\"),\n );\n }\n\n const ok = !problems.some((p) => p.level === \"error\");\n return ok ? { ok, manifest: m as unknown as NodePackageManifest, problems } : { ok, problems };\n}\n\nfunction validateKind(kind: unknown, problems: ManifestProblem[]): void {\n if (typeof kind !== \"string\" || kind.trim() === \"\") {\n problems.push(err(\"kind\", \"Required — the canonical kind id this package provides.\"));\n return;\n }\n if (!NAMESPACED_KIND.test(kind)) {\n // Un-namespaced ids are the one mistake that cannot be fixed after the\n // fact: the ambiguous string is already written into saved documents.\n problems.push(\n err(\"kind\", `\"${kind}\" must be namespaced as @scope/name — a bare id makes stored graphs ambiguous, and that is unfixable once documents carry it.`),\n );\n return;\n }\n if (kind.startsWith(FIRST_PARTY_SCOPE)) {\n problems.push(\n warn(\"kind\", `${FIRST_PARTY_SCOPE}* is reserved for first-party nodes; the registry will reject this unless the package is first-party.`),\n );\n }\n}\n\nfunction validateAliases(aliases: unknown, problems: ManifestProblem[]): void {\n if (aliases === undefined) return;\n\n if (!Array.isArray(aliases) || aliases.some((a) => typeof a !== \"string\" || a.trim() === \"\")) {\n problems.push(err(\"aliases\", \"Must be an array of non-empty id strings.\"));\n }\n}\n\nfunction validateRuntimes(runtimes: unknown, problems: ManifestProblem[]): void {\n if (typeof runtimes !== \"object\" || runtimes === null || Array.isArray(runtimes)) {\n problems.push(err(\"runtimes\", \"Required — an object of runtime id to { entry | package, engine }.\"));\n return;\n }\n\n const entries = Object.entries(runtimes as Record<string, unknown>);\n if (entries.length === 0) {\n problems.push(err(\"runtimes\", \"A node that implements no runtime cannot execute anywhere.\"));\n return;\n }\n\n for (const [runtime, spec] of entries) {\n if (typeof spec !== \"object\" || spec === null || Array.isArray(spec)) {\n problems.push(err(`runtimes.${runtime}`, \"Must be an object of { entry | package, engine }.\"));\n continue;\n }\n\n const s = spec as Record<string, unknown>;\n const hasEntry = typeof s.entry === \"string\" && s.entry.trim() !== \"\";\n const hasPackage = typeof s.package === \"string\" && s.package.trim() !== \"\";\n\n if (!hasEntry && !hasPackage) {\n problems.push(err(`runtimes.${runtime}`, \"Needs `entry` (a module path) or `package` (a dependency requirement).\"));\n }\n if (hasEntry && hasPackage) {\n problems.push(err(`runtimes.${runtime}`, \"Declare `entry` or `package`, not both — which one is authoritative is otherwise ambiguous.\"));\n }\n if (typeof s.engine !== \"string\" || s.engine.trim() === \"\") {\n problems.push(\n err(`runtimes.${runtime}.engine`, `Required — the semver range of the ${runtime} engine. Without it, this node installs against a ${runtime} engine too old to run it.`),\n );\n }\n }\n}\n\nfunction validateCapabilities(capabilities: unknown, problems: ManifestProblem[]): void {\n if (capabilities === undefined) return;\n\n if (typeof capabilities !== \"object\" || capabilities === null || Array.isArray(capabilities)) {\n problems.push(\n err(\"capabilities\", 'Must be an object of capability id to \"required\" | \"optional\" — a bare list cannot say whether the node works without one.'),\n );\n return;\n }\n\n for (const [id, requirement] of Object.entries(capabilities as Record<string, unknown>)) {\n if (!REQUIREMENTS.includes(requirement as string)) {\n problems.push(err(`capabilities.${id}`, `Must be \"required\" or \"optional\".`));\n }\n }\n}\n\n/**\n * Check a node against the runtimes a host executes on, and their versions.\n *\n * Two failures live here, and both are errors because the node genuinely\n * cannot run: a runtime the package does not implement at all, and a runtime\n * it implements against an engine newer than the host's.\n *\n * `engineVersions` is optional — pass what the host knows. An unchecked range\n * is reported as a warning rather than passed over silently, because \"we did\n * not check\" and \"it is fine\" must not look the same.\n */\nexport function checkRuntimeSupport(\n manifest: Pick<NodePackageManifest, \"kind\" | \"runtimes\">,\n hostRuntimes: readonly string[],\n engineVersions?: Readonly<Record<string, string>>,\n): ManifestProblem[] {\n const runtimes = manifest.runtimes ?? {};\n const provided = Object.keys(runtimes);\n const problems: ManifestProblem[] = [];\n\n const missing = hostRuntimes.filter((r) => !provided.includes(r));\n if (missing.length > 0) {\n problems.push(\n err(\n \"runtimes\",\n `${manifest.kind} implements ${provided.join(\", \") || \"no runtime\"} but this project executes on ${missing.join(\", \")}. The node would install, appear in the palette, and then fail to run.`,\n ),\n );\n }\n\n for (const runtime of hostRuntimes) {\n const spec = (runtimes as Record<string, NodeRuntimeSpec | undefined>)[runtime];\n if (!spec) continue;\n\n const hostVersion = engineVersions?.[runtime];\n if (hostVersion === undefined) {\n problems.push(\n warn(`runtimes.${runtime}.engine`, `${manifest.kind} needs ${runtime} engine ${spec.engine}; this host did not report its ${runtime} version, so the range was not checked.`),\n );\n continue;\n }\n\n if (!satisfiesRange(hostVersion, spec.engine)) {\n problems.push(\n err(`runtimes.${runtime}.engine`, `${manifest.kind} needs ${runtime} engine ${spec.engine}, but this host runs ${hostVersion}.`),\n );\n }\n }\n\n return problems;\n}\n\n/**\n * Minimal semver range check — `^x.y.z`, `~x.y.z`, `>=x.y.z`, `x.y.z`, `*`.\n *\n * Deliberately small: this runs in the CLI and in CI, and pulling a semver\n * library into the engine for one comparison is not worth the dependency. It\n * covers the forms a manifest actually uses; anything it cannot parse is\n * treated as unsatisfied rather than silently passed, so an unparseable range\n * fails loudly instead of waving a node through.\n */\nexport function satisfiesRange(version: string, range: string): boolean {\n const trimmed = range.trim();\n if (trimmed === \"*\" || trimmed === \"\") return true;\n\n const v = parseVersion(version);\n if (!v) return false;\n\n for (const clause of trimmed.split(\"||\").map((c) => c.trim())) {\n if (satisfiesClause(v, clause)) return true;\n }\n return false;\n}\n\nfunction satisfiesClause(v: [number, number, number], clause: string): boolean {\n const m = /^(\\^|~|>=|>|<=|<|=)?\\s*v?(\\d+)(?:\\.(\\d+))?(?:\\.(\\d+))?/.exec(clause);\n if (!m) return false;\n\n const op = m[1] ?? \"=\";\n const target: [number, number, number] = [Number(m[2]), Number(m[3] ?? 0), Number(m[4] ?? 0)];\n const cmp = compare(v, target);\n\n switch (op) {\n case \">=\":\n return cmp >= 0;\n case \">\":\n return cmp > 0;\n case \"<=\":\n return cmp <= 0;\n case \"<\":\n return cmp < 0;\n case \"=\":\n return cmp === 0;\n case \"~\":\n // Same major+minor, patch may rise.\n return cmp >= 0 && v[0] === target[0] && v[1] === target[1];\n case \"^\":\n // Below 1.0.0 a minor bump is breaking, so ^0.5 means 0.5.x — which is\n // the range every pre-1.0 package in this suite actually needs.\n if (target[0] === 0) return cmp >= 0 && v[0] === 0 && v[1] === target[1];\n return cmp >= 0 && v[0] === target[0];\n default:\n return false;\n }\n}\n\nfunction parseVersion(version: string): [number, number, number] | null {\n const m = /^v?(\\d+)\\.(\\d+)(?:\\.(\\d+))?/.exec(version.trim());\n return m ? [Number(m[1]), Number(m[2]), Number(m[3] ?? 0)] : null;\n}\n\nfunction compare(a: [number, number, number], b: [number, number, number]): number {\n for (let i = 0; i < 3; i++) {\n if (a[i] !== b[i]) return a[i] < b[i] ? -1 : 1;\n }\n return 0;\n}\n\n/**\n * Check that every capability a node needs is wired.\n *\n * A `required` capability that is missing is an ERROR — that is the whole point\n * of the requirement level. It is meant to be surfaced at author time, so an\n * editor can grey the node and name what the host never registered, rather than\n * the node installing cleanly and silently no-opping during a run.\n *\n * An `optional` one is a warning: the node still works, with less.\n */\nexport function checkCapabilities(\n manifest: Pick<NodePackageManifest, \"kind\" | \"capabilities\">,\n available: Readonly<Record<string, boolean>>,\n): ManifestProblem[] {\n const needed = manifest.capabilities ?? {};\n const problems: ManifestProblem[] = [];\n\n for (const [id, requirement] of Object.entries(needed)) {\n if (available[id] === true) continue;\n\n problems.push(\n requirement === \"required\"\n ? err(\"capabilities\", `${manifest.kind} requires the ${id} capability, which this host has not registered. The node cannot run here.`)\n : warn(\"capabilities\", `${manifest.kind} can use the ${id} capability, which this host has not registered. The node runs with reduced behaviour.`),\n );\n }\n\n return problems;\n}\n","import type { FlowGraph } from \"../types\";\n\n/**\n * Host capabilities — the services core nodes need but must never depend on.\n *\n * A node that imports a provider SDK forces every consumer to install it: a\n * workflow app that never calls a model should not inherit an LLM dependency.\n * So core declares the CONTRACT and the host supplies the implementation, the\n * same arrangement `renderDocumentField` already uses for documents.\n *\n * That keeps opinionated nodes in core without their opinions: `llm_branch`\n * ships the routing semantics, port derivation and config UI, while whichever\n * client the host registers — Prism, an OpenAI SDK, a local model, a fake in a\n * test — decides how the question actually gets asked.\n *\n * Registration is deliberately explicit and typed per capability rather than a\n * stringly-keyed bag, so a missing one is a clear error at the seam instead of\n * an undefined somewhere downstream.\n */\n\n// ── LLM ─────────────────────────────────────────────────────────────────────\n\nexport type LlmRoute = { port: string; description?: string };\n\nexport type LlmRouteRequest = {\n /** Optional framing for the decision. */\n system?: string;\n /** What the model is deciding about. */\n prompt: string;\n /** The ports it must choose between. */\n routes: LlmRoute[];\n provider?: string;\n model?: string;\n /** Host-resolved credential reference, never a raw key. */\n credential?: string;\n};\n\nexport type LlmRouteChoice = {\n /** Must be one of the requested route ports. */\n port: string;\n /** Why — carried down the chosen port so a run is explainable afterwards. */\n reason?: string;\n};\n\n/**\n * The only thing core asks of an LLM: given routes, pick one.\n *\n * Deliberately not a general chat interface. A narrow contract is one a host\n * can satisfy in a few lines over any SDK, and it keeps the choice\n * machine-checkable — an implementation should constrain the model to the\n * declared ports (structured output / enum) rather than parsing prose.\n */\nexport type LlmClient = {\n chooseRoute: (request: LlmRouteRequest) => Promise<LlmRouteChoice> | LlmRouteChoice;\n};\n\nlet llmClient: LlmClient | null = null;\n\n/** Install the host's LLM client. Returns an unregister function. */\nexport function registerLlmClient(client: LlmClient): () => void {\n llmClient = client;\n return () => {\n if (llmClient === client) llmClient = null;\n };\n}\n\nexport function getLlmClient(): LlmClient | null {\n return llmClient;\n}\n\n// ── Workflow resolution ─────────────────────────────────────────────────────\n\n/**\n * Why a workflow reference could not be resolved.\n *\n * `missing` and `version-mismatch` are deliberately distinct. Collapsing them\n * into a bare null makes \"no such workflow\" indistinguishable from \"that\n * workflow exists, but it is not the one you pinned\" — and the second wants an\n * error naming both versions, because it is the interesting failure.\n */\nexport type WorkflowResolutionFailure = {\n reason: \"missing\" | \"version-mismatch\";\n /** The version the host actually holds, when it holds one. */\n available?: number;\n message?: string;\n};\n\nexport type WorkflowResolution = FlowGraph | WorkflowResolutionFailure | null;\n\n/**\n * Resolve a workflow reference to a runnable graph.\n *\n * `subflow` names another workflow rather than embedding it, so the host owns\n * where workflows live — a database, a file, an API.\n *\n * ## Why `version` is here\n *\n * A workflow another workflow depends on is an INTERFACE, and interfaces need\n * pins. Without a version, a parent goes on calling `invoice-triage`, someone\n * edits that child, and the parent now runs different logic having reported\n * success the whole time — correct-looking, no error, wrong behaviour. The same\n * failure family as the 0.9.0 routing divergence.\n *\n * The parameter lives on the resolver rather than being encoded into the ref\n * string (`invoice-triage@3`) because a stringly-typed protocol is one every\n * host invents differently — the \"three vocabularies for one node\" problem.\n *\n * Raised by the MOIC Suite consumer, whose `workflow_ref` pins versions and\n * fails loudly on mismatch. Their point: a host COULD NOT implement pinning\n * before this, because the node had no way to ask and the resolver no way to\n * receive.\n *\n * Returning `null` still means \"no such workflow\". Return a\n * {@link WorkflowResolutionFailure} to distinguish a version mismatch.\n */\nexport type WorkflowResolver = (\n ref: string,\n version?: number,\n) => Promise<WorkflowResolution> | WorkflowResolution;\n\n/** Narrow a resolver's return value to an explicit failure. */\nexport function isResolutionFailure(value: WorkflowResolution): value is WorkflowResolutionFailure {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"reason\" in value &&\n (value as WorkflowResolutionFailure).reason !== undefined\n );\n}\n\nlet workflowResolver: WorkflowResolver | null = null;\n\n/** Install the host's workflow resolver. Returns an unregister function. */\nexport function registerWorkflowResolver(resolver: WorkflowResolver): () => void {\n workflowResolver = resolver;\n return () => {\n if (workflowResolver === resolver) workflowResolver = null;\n };\n}\n\nexport function getWorkflowResolver(): WorkflowResolver | null {\n return workflowResolver;\n}\n\n// ── Introspection ───────────────────────────────────────────────────────────\n\nexport type CapabilityId = \"llm\" | \"workflow_resolver\" | \"document\";\n\n/**\n * Which capabilities are currently satisfied.\n *\n * Exists so a host (or the CLI, or an agent over MCP) can answer \"what does\n * this graph need that I haven't wired?\" BEFORE a run fails halfway through.\n */\nexport function capabilityStatus(): Record<CapabilityId, boolean> {\n // Imported lazily to avoid dragging the React-dependent rich-input module\n // into the headless engine.\n let documentReady = false;\n try {\n // eslint-disable-next-line @typescript-eslint/no-var-requires, no-undef\n documentReady = Boolean((globalThis as any).__fancyFlowDocumentAdapter);\n } catch {\n documentReady = false;\n }\n return {\n llm: llmClient !== null,\n workflow_resolver: workflowResolver !== null,\n document: documentReady,\n };\n}\n","/**\n * Golden fixtures — the parity guarantee, and a publishing requirement.\n *\n * Every runtime a node package claims runs these same JSON cases. That is what\n * makes \"this node behaves identically on TS and PHP\" verified rather than\n * asserted, and it is the one thing a loose collection of repos can never\n * offer.\n *\n * WHY IT IS REQUIRED RATHER THAN ENCOURAGED: cross-runtime drift does not fail\n * loudly. The 0.9.0 port-resolution divergence produced flows that routed\n * correctly in the editor and silently down one path on the server — status\n * `completed`, no error, no exception, nothing to alert on. A guarantee that\n * only holds when an author opts in is not a guarantee.\n *\n * WHAT A CASE ASSERTS, and why it matters more than it looks:\n *\n * A fixture asserts THE DOWNSTREAM NODE EXECUTED — not the port the node\n * recorded. The distinction is the whole lesson of that incident. A test\n * reading back `outputs.router.__port` stays green while no edge fires and\n * the run halts at the branch: the node faithfully recorded its choice, and\n * nothing downstream ever ran. So the runner wires a real probe to every\n * declared port and reports which probes actually executed.\n *\n * The format is plain JSON with no expressions or callbacks, so the PHP runner\n * executes byte-identical cases without an embedded JS engine.\n */\n\nimport { runFlow } from \"../runtime/run-flow\";\nimport { getNodeKind } from \"../registry/registry\";\nimport { resolveNodePorts } from \"../registry/ports\";\nimport { decodePause, type PauseAwaiting } from \"../registry/pause\";\nimport { registerLlmClient, registerWorkflowResolver } from \"../registry/capabilities\";\nimport type { FlowGraph, FlowNode, NodeExecutor, RunEvent } from \"../types\";\n\n/**\n * Deterministic stand-ins for host capabilities, declared as DATA.\n *\n * `llm_router` cannot reach a provider in CI, so a fixture has to supply a fake\n * `LlmClient`. If the stub format is not shared, each runtime stubs\n * differently and the fixtures stop being comparable — parity theatre. So the\n * fixture declares the stub's *behaviour* and both engines construct it\n * identically from the same JSON.\n */\nexport type FixtureStubs = {\n /** Canned `chooseRoute` answer for the LLM capability. */\n llm_client?: { chooseRoute: { port: string; reason?: string } };\n /** Canned workflow resolution, keyed by ref, for `subflow`. */\n workflow_resolver?: Record<string, FlowGraph | null>;\n};\n\n/** An event a case expects the run to have emitted. */\nexport type FixtureEventExpectation = {\n type: RunEvent[\"type\"];\n /** Emitting node, when it matters. */\n nodeId?: string;\n level?: \"info\" | \"warn\" | \"error\";\n /** Substring match against the message — full text is too brittle to pin. */\n messageContains?: string;\n};\n\n/** What a case expects to have happened. */\nexport type FixtureExpectation = {\n /**\n * Output ports whose downstream node must have executed — the assertion that\n * catches routing drift. Order-insensitive; the set must match exactly, so a\n * node that fires an extra port fails just as loudly as one that fires none.\n */\n ports?: string[];\n /** The value carried downstream, deep-compared when present. */\n value?: unknown;\n /** The run halted for a person. */\n pause?: { awaiting: PauseAwaiting; detail?: unknown };\n /** The run failed, and the message contains this substring. */\n error?: string;\n /**\n * Events the run must have emitted.\n *\n * Emitted events are BEHAVIOUR, not decoration. The hallucinated-port warning\n * is a contract an operator relies on to know a run took the fallback — if\n * one runtime stops emitting it, the guarantee degrades silently. Each entry\n * must match at least one emitted event.\n */\n events?: FixtureEventExpectation[];\n /**\n * The run resumed after a pause and reached this state.\n *\n * Pause/resume is the ONLY path that crosses a persistence boundary, which\n * makes it where two runtimes are most likely to drift — and it had no parity\n * coverage at all while `PausesForHuman` became public API.\n */\n afterResume?: {\n /** Delivered on the paused node's `values` input, as a host would on resume. */\n submit: unknown;\n ports?: string[];\n value?: unknown;\n error?: string;\n };\n};\n\nexport type FixtureCase = {\n /** Human-readable, and what a failure report names. */\n name: string;\n /** Config for the node under test — drives config-derived ports. */\n config?: Record<string, unknown>;\n /**\n * The node's resolved output ports, stated rather than derived.\n *\n * NOT a convenience. TS derives config-driven ports by running a JavaScript\n * function (`switch_case`'s cases, `llm_router`'s routes); PHP cannot, and\n * falls back to the kind's static declaration. Left there, the identical\n * fixture would build a DIFFERENT graph on each runtime — the fixtures would\n * silently stop comparing like with like, which is the exact failure they\n * exist to catch.\n *\n * So a case states its ports the same way an exported document does (see\n * 0.10.1, \"serialize resolved ports\"), and both runners honour it. Omit it\n * only for a node whose ports are static.\n */\n ports?: string[];\n /** Inputs delivered on the node's input ports. */\n inputs?: Record<string, unknown>;\n /**\n * Run this case against an ALIAS or an older config shape.\n *\n * What proves `aliases` and `configVersion` actually work rather than being\n * declared and rotting. A package that renames its kind should have a case\n * pinning that the old id still resolves.\n */\n legacyKind?: string;\n /** Deterministic capability stand-ins for this case. */\n stubs?: FixtureStubs;\n expect: FixtureExpectation;\n};\n\nexport type FixtureFile = {\n /** The kind under test. Must match the manifest's `kind`. */\n kind: string;\n cases: FixtureCase[];\n};\n\nexport type FixtureFailure = {\n case: string;\n message: string;\n};\n\nexport type FixtureRunResult = {\n ok: boolean;\n passed: number;\n failures: FixtureFailure[];\n};\n\nconst SUBJECT = \"subject\";\nconst TRIGGER = \"trigger\";\nconst probeId = (port: string) => `probe:${port}`;\n\n/**\n * Build the graph a case runs in: a trigger, the node under test, and one\n * probe per declared output port.\n *\n * The probes are the point. Reading the subject's return value would tell us\n * what it *recorded*; only a probe tells us what actually reached a downstream\n * node through a real edge.\n */\nfunction buildGraph(kindId: string, testCase: FixtureCase): { graph: FlowGraph; ports: string[] } {\n const subject: FlowNode = {\n id: SUBJECT,\n type: kindId,\n position: { x: 0, y: 100 },\n data: { kind: kindId, config: testCase.config ?? {} },\n } as unknown as FlowNode;\n\n const kind = getNodeKind(kindId) ?? undefined;\n // An explicitly declared port list wins, so both runtimes build the same\n // graph even where one can derive config-driven ports and the other cannot.\n const ports = testCase.ports ?? (resolveNodePorts(subject, kind).outputs ?? []).map((p) => p.id);\n const effective = ports.length ? ports : [\"out\"];\n\n const nodes: FlowNode[] = [\n { id: TRIGGER, type: \"manual_trigger\", position: { x: 0, y: 0 }, data: {} } as unknown as FlowNode,\n subject,\n ...effective.map(\n (port, i) =>\n ({\n id: probeId(port),\n type: \"@particle-academy/transform\",\n position: { x: i * 200, y: 200 },\n data: {},\n }) as unknown as FlowNode,\n ),\n ];\n\n const edges = [\n { id: `e:trigger`, source: TRIGGER, target: SUBJECT },\n ...effective.map((port) => ({\n id: `e:${port}`,\n source: SUBJECT,\n sourceHandle: port,\n target: probeId(port),\n })),\n ];\n\n return { graph: { nodes, edges } as FlowGraph, ports: effective };\n}\n\nfunction deepEqual(a: unknown, b: unknown): boolean {\n return JSON.stringify(a) === JSON.stringify(b);\n}\n\n/**\n * Install the case's capability stubs, returning a function that removes them.\n *\n * Constructed here from the fixture's JSON rather than supplied by the caller,\n * which is the whole point: both runtimes build the same stub from the same\n * data, so a fixture covering `llm_router` compares like with like instead of\n * comparing two different fakes.\n */\nfunction installStubs(stubs: FixtureStubs | undefined): () => void {\n if (!stubs) return () => {};\n\n const teardown: Array<() => void> = [];\n\n if (stubs.llm_client) {\n const answer = stubs.llm_client.chooseRoute;\n teardown.push(registerLlmClient({ chooseRoute: () => ({ ...answer }) }));\n }\n\n if (stubs.workflow_resolver) {\n const table = stubs.workflow_resolver;\n teardown.push(registerWorkflowResolver((ref) => table[ref] ?? null));\n }\n\n return () => teardown.forEach((fn) => fn());\n}\n\nfunction matchesEvent(event: RunEvent, want: FixtureEventExpectation): boolean {\n if (event.type !== want.type) return false;\n\n const e = event as Record<string, unknown>;\n if (want.nodeId !== undefined && e.nodeId !== want.nodeId) return false;\n if (want.level !== undefined && e.level !== want.level) return false;\n if (want.messageContains !== undefined && !String(e.message ?? \"\").includes(want.messageContains)) return false;\n\n return true;\n}\n\n/**\n * Re-run a paused case with a submission delivered, as a durable host would.\n *\n * The submission arrives on `values` because that is the input the builtin\n * human nodes read, and a third-party pausing node that wants fixture coverage\n * should follow the same convention rather than inventing its own.\n */\nasync function resume(\n kindId: string,\n testCase: FixtureCase,\n executor: NodeExecutor,\n pausedNodeId: string,\n submit: unknown,\n): Promise<{ ok: boolean; error?: string; fired: string[]; carried: unknown }> {\n const { graph } = buildGraph(kindId, testCase);\n const fired: string[] = [];\n let carried: unknown;\n\n const executors: Record<string, NodeExecutor> = {\n manual_trigger: () => testCase.inputs ?? {},\n \"@particle-academy/manual_trigger\": () => testCase.inputs ?? {},\n [kindId]: executor,\n };\n\n // The resumed node sees its submission, exactly as the durable runner\n // injects one.\n executors[pausedNodeId] = ((c: Parameters<NodeExecutor>[0]) =>\n executor({ ...c, inputs: { ...(c.inputs as object), values: submit } })) as NodeExecutor;\n\n for (const node of graph.nodes) {\n if (!node.id.startsWith(\"probe:\")) continue;\n const port = node.id.slice(\"probe:\".length);\n executors[node.id] = ((c: { inputs: Record<string, unknown> }) => {\n fired.push(port);\n carried = c.inputs?.in ?? c.inputs;\n return undefined;\n }) as unknown as NodeExecutor;\n }\n\n const releaseStubs = installStubs(testCase.stubs);\n const result = await runFlow(graph, executors, () => {});\n releaseStubs();\n\n return { ok: result.ok, error: result.error, fired, carried };\n}\n\n/**\n * Run one fixture file against a kind's executor.\n *\n * `executor` is the node's own; everything else in the graph is supplied here,\n * so a case exercises the node and nothing but the node.\n */\nexport async function runFixtures(\n file: FixtureFile,\n executor: NodeExecutor,\n): Promise<FixtureRunResult> {\n const failures: FixtureFailure[] = [];\n let passed = 0;\n\n for (const testCase of file.cases) {\n // A case may run against an alias or an older id, which is what proves the\n // package's `aliases` declaration is real rather than decorative.\n const kindId = testCase.legacyKind ?? file.kind;\n const { graph } = buildGraph(kindId, testCase);\n const fired: string[] = [];\n const events: RunEvent[] = [];\n let carried: unknown;\n\n const releaseStubs = installStubs(testCase.stubs);\n\n const executors: Record<string, NodeExecutor> = {\n manual_trigger: () => testCase.inputs ?? {},\n \"@particle-academy/manual_trigger\": () => testCase.inputs ?? {},\n [kindId]: executor,\n };\n\n // A probe per port, bound by NODE ID — `pickExecutor` checks that before\n // kind, so each probe reports which specific port reached it. Recording\n // here, rather than inspecting the subject's result, is what makes this\n // assert reachability instead of intent.\n for (const node of graph.nodes) {\n if (!node.id.startsWith(\"probe:\")) continue;\n const port = node.id.slice(\"probe:\".length);\n executors[node.id] = ((ctx: { inputs: Record<string, unknown> }) => {\n fired.push(port);\n carried = ctx.inputs?.in ?? ctx.inputs;\n return undefined;\n }) as unknown as NodeExecutor;\n }\n\n const result = await runFlow(graph, executors, (e) => events.push(e));\n releaseStubs();\n\n const fail = (message: string) => failures.push({ case: testCase.name, message });\n const expected = testCase.expect;\n let caseOk = true;\n\n if (expected.pause) {\n const paused = decodePause(result.error);\n if (!paused) {\n caseOk = false;\n fail(`expected a pause awaiting \"${expected.pause.awaiting}\", got ${result.ok ? \"a completed run\" : `error: ${result.error}`}`);\n } else {\n if (paused.awaiting !== expected.pause.awaiting) {\n caseOk = false;\n fail(`expected pause awaiting \"${expected.pause.awaiting}\", got \"${paused.awaiting}\"`);\n }\n if (\"detail\" in expected.pause && !deepEqual(paused.detail, expected.pause.detail)) {\n caseOk = false;\n fail(`pause detail mismatch: expected ${JSON.stringify(expected.pause.detail)}, got ${JSON.stringify(paused.detail)}`);\n }\n }\n } else if (expected.error !== undefined) {\n if (result.ok) {\n caseOk = false;\n fail(`expected an error containing \"${expected.error}\", but the run succeeded`);\n } else if (!String(result.error ?? \"\").includes(expected.error)) {\n caseOk = false;\n fail(`expected an error containing \"${expected.error}\", got \"${result.error}\"`);\n }\n } else {\n if (expected.ports !== undefined) {\n const got = [...fired].sort();\n const want = [...expected.ports].sort();\n if (!deepEqual(got, want)) {\n caseOk = false;\n // Name the failure in terms of reachability, because that is what\n // the assertion means and what a reader needs to act on.\n fail(\n `expected these ports to reach a downstream node: [${want.join(\", \")}], but [${got.join(\", \")}] did` +\n (result.ok ? \"\" : ` (run error: ${result.error})`),\n );\n }\n }\n if (\"value\" in expected && !deepEqual(carried, expected.value)) {\n caseOk = false;\n fail(`expected the value carried downstream to be ${JSON.stringify(expected.value)}, got ${JSON.stringify(carried)}`);\n }\n }\n\n // Emitted events are behaviour, not decoration — an operator relies on the\n // hallucinated-port warning to know a run took the fallback.\n for (const want of expected.events ?? []) {\n if (!events.some((e) => matchesEvent(e, want))) {\n caseOk = false;\n fail(`expected an emitted event matching ${JSON.stringify(want)}, but none of the ${events.length} emitted events did`);\n }\n }\n\n // Resume: the only path crossing a persistence boundary, and so the one\n // most likely to drift between runtimes.\n if (expected.afterResume) {\n const paused = decodePause(result.error);\n if (!paused) {\n caseOk = false;\n fail(\"expected the run to pause before resuming, but it never paused\");\n } else {\n const resumed = await resume(kindId, testCase, executor, paused.nodeId, expected.afterResume.submit);\n const want = expected.afterResume;\n\n if (want.error !== undefined) {\n if (resumed.ok || !String(resumed.error ?? \"\").includes(want.error)) {\n caseOk = false;\n fail(`after resume: expected an error containing \"${want.error}\", got ${resumed.ok ? \"success\" : `\"${resumed.error}\"`}`);\n }\n }\n if (want.ports !== undefined) {\n const got = [...resumed.fired].sort();\n const wanted = [...want.ports].sort();\n if (!deepEqual(got, wanted)) {\n caseOk = false;\n fail(`after resume: expected ports [${wanted.join(\", \")}] to reach a downstream node, but [${got.join(\", \")}] did`);\n }\n }\n if (\"value\" in want && !deepEqual(resumed.carried, want.value)) {\n caseOk = false;\n fail(`after resume: expected the value carried downstream to be ${JSON.stringify(want.value)}, got ${JSON.stringify(resumed.carried)}`);\n }\n }\n }\n\n if (caseOk) passed += 1;\n }\n\n return { ok: failures.length === 0, passed, failures };\n}\n\n/**\n * Validate a fixture file's shape before running it.\n *\n * A package that publishes an empty or malformed fixture file has satisfied the\n * letter of the requirement and none of its purpose, so this is checked at\n * publish rather than trusted.\n */\nexport function validateFixtureFile(input: unknown, expectedKind?: string): string[] {\n const problems: string[] = [];\n\n if (typeof input !== \"object\" || input === null || Array.isArray(input)) {\n return [\"Fixture file must be a JSON object.\"];\n }\n\n const f = input as Record<string, unknown>;\n\n if (typeof f.kind !== \"string\" || f.kind.trim() === \"\") {\n problems.push(\"`kind` is required — the kind these cases exercise.\");\n } else if (expectedKind && f.kind !== expectedKind) {\n problems.push(`\\`kind\\` is \"${f.kind}\" but the manifest declares \"${expectedKind}\".`);\n }\n\n if (!Array.isArray(f.cases) || f.cases.length === 0) {\n problems.push(\"`cases` must contain at least one case — an empty fixture file proves nothing.\");\n return problems;\n }\n\n // At least one case must exercise a failure.\n //\n // \"Does it fail the same way\" deserves equal weight to \"does it succeed the\n // same way\": the incident that motivated this whole mechanism was a FAILURE\n // that reported `completed` with no error. A suite that only covers happy\n // paths cannot catch a runtime that fails differently — or does not fail\n // at all.\n const coversFailure = f.cases.some((c: unknown) => {\n const expect = (c as { expect?: Record<string, unknown> })?.expect;\n return Boolean(expect && (\"error\" in expect || \"pause\" in expect));\n });\n if (!coversFailure) {\n problems.push(\n \"At least one case must assert a failure (`expect.error`) or a pause (`expect.pause`). Every case here covers a success path, and the divergence this format exists to catch reported success while doing nothing.\",\n );\n }\n\n f.cases.forEach((c: unknown, i: number) => {\n const label = `cases[${i}]`;\n if (typeof c !== \"object\" || c === null) {\n problems.push(`${label} must be an object.`);\n return;\n }\n const testCase = c as Record<string, unknown>;\n if (typeof testCase.name !== \"string\" || testCase.name.trim() === \"\") {\n problems.push(`${label}.name is required — a failure report names it.`);\n }\n if (typeof testCase.expect !== \"object\" || testCase.expect === null) {\n problems.push(`${label}.expect is required — a case that asserts nothing passes vacuously.`);\n return;\n }\n const expect = testCase.expect as Record<string, unknown>;\n if (\n expect.ports === undefined &&\n expect.value === undefined &&\n expect.pause === undefined &&\n expect.error === undefined\n ) {\n problems.push(`${label}.expect must assert at least one of: ports, value, pause, error.`);\n }\n if (expect.ports !== undefined && (!Array.isArray(expect.ports) || expect.ports.some((p) => typeof p !== \"string\"))) {\n problems.push(`${label}.expect.ports must be an array of port id strings.`);\n }\n });\n\n return problems;\n}\n"]}
package/dist/engine.d.cts CHANGED
@@ -1,6 +1,6 @@
1
- export { R as RunOptions, a as RunResult, r as runFlow } from './run-flow-VKm57Hcj.cjs';
2
- import { F as FlowGraph, R as RunEvent, N as NodeExecutor } from './types-sOmpCitB.cjs';
3
- export { A as ActionNodeData, B as BaseNodeData, D as DecisionNodeData, E as ExecutorRegistry, a as FlowEdge, b as FlowNode, c as FlowNodeData, d as FlowNodeKind, e as NodeRunStatus, f as NoteNodeData, O as OutputNodeData, P as PortDescriptor, S as SubgraphNodeData, T as TriggerNodeData } from './types-sOmpCitB.cjs';
1
+ export { R as RunOptions, a as RunResult, r as runFlow } from './run-flow-AXzOR-Wq.cjs';
2
+ import { F as FlowGraph, R as RunEvent, N as NodeExecutor } from './types-CMSrWVYM.cjs';
3
+ export { A as ActionNodeData, B as BaseNodeData, D as DecisionNodeData, E as ExecutorRegistry, b as FlowEdge, a as FlowNode, c as FlowNodeData, d as FlowNodeKind, e as NodeRunStatus, f as NoteNodeData, O as OutputNodeData, P as PortDescriptor, S as SubgraphNodeData, T as TriggerNodeData } from './types-CMSrWVYM.cjs';
4
4
  import { P as PauseAwaiting } from './pause-9iT4tCEV.cjs';
5
5
  export { L as LEGACY_PAUSE_PREFIXES, a as PAUSE_PREFIX, b as PauseSignal, d as decodePause, e as encodePause, i as isPause, p as pauseForHuman } from './pause-9iT4tCEV.cjs';
6
6
  import '@xyflow/react';
package/dist/engine.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- export { R as RunOptions, a as RunResult, r as runFlow } from './run-flow-ChBi6q-W.js';
2
- import { F as FlowGraph, R as RunEvent, N as NodeExecutor } from './types-sOmpCitB.js';
3
- export { A as ActionNodeData, B as BaseNodeData, D as DecisionNodeData, E as ExecutorRegistry, a as FlowEdge, b as FlowNode, c as FlowNodeData, d as FlowNodeKind, e as NodeRunStatus, f as NoteNodeData, O as OutputNodeData, P as PortDescriptor, S as SubgraphNodeData, T as TriggerNodeData } from './types-sOmpCitB.js';
1
+ export { R as RunOptions, a as RunResult, r as runFlow } from './run-flow-9U-gaYVF.js';
2
+ import { F as FlowGraph, R as RunEvent, N as NodeExecutor } from './types-CMSrWVYM.js';
3
+ export { A as ActionNodeData, B as BaseNodeData, D as DecisionNodeData, E as ExecutorRegistry, b as FlowEdge, a as FlowNode, c as FlowNodeData, d as FlowNodeKind, e as NodeRunStatus, f as NoteNodeData, O as OutputNodeData, P as PortDescriptor, S as SubgraphNodeData, T as TriggerNodeData } from './types-CMSrWVYM.js';
4
4
  import { P as PauseAwaiting } from './pause-9iT4tCEV.js';
5
5
  export { L as LEGACY_PAUSE_PREFIXES, a as PAUSE_PREFIX, b as PauseSignal, d as decodePause, e as encodePause, i as isPause, p as pauseForHuman } from './pause-9iT4tCEV.js';
6
6
  import '@xyflow/react';
package/dist/engine.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { decodePause } from './chunk-UEOE6B52.js';
2
2
  export { LEGACY_PAUSE_PREFIXES, PAUSE_PREFIX, decodePause, encodePause, isPause, pauseForHuman } from './chunk-UEOE6B52.js';
3
- import { runFlow } from './chunk-L4AX73Q6.js';
4
- export { runFlow } from './chunk-L4AX73Q6.js';
3
+ import { runFlow } from './chunk-KDHLKBL2.js';
4
+ export { runFlow } from './chunk-KDHLKBL2.js';
5
5
  import { resolveNodePorts } from './chunk-TITD5W4Y.js';
6
- import { getNodeKind } from './chunk-U5F22BHV.js';
6
+ import { getNodeKind } from './chunk-YXRLIV7A.js';
7
7
  import { registerLlmClient, registerWorkflowResolver } from './chunk-USL4FMFU.js';
8
8
 
9
9
  // src/marketplace/manifest.ts