@particle-academy/fancy-flow 0.24.0 → 0.25.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 (41) hide show
  1. package/dist/{chunk-QAA4CA22.js → chunk-ATQXZEVD.js} +117 -6
  2. package/dist/chunk-ATQXZEVD.js.map +1 -0
  3. package/dist/{chunk-OHVSEHDC.js → chunk-N5ICD2WZ.js} +3 -3
  4. package/dist/{chunk-OHVSEHDC.js.map → chunk-N5ICD2WZ.js.map} +1 -1
  5. package/dist/{chunk-ZS6DVGB3.js → chunk-OFW7GN3Y.js} +4 -4
  6. package/dist/{chunk-ZS6DVGB3.js.map → chunk-OFW7GN3Y.js.map} +1 -1
  7. package/dist/{chunk-YXRLIV7A.js → chunk-Q6IPK64P.js} +4 -2
  8. package/dist/chunk-Q6IPK64P.js.map +1 -0
  9. package/dist/{chunk-KDHLKBL2.js → chunk-U2VJB7HR.js} +7 -5
  10. package/dist/chunk-U2VJB7HR.js.map +1 -0
  11. package/dist/engine.cjs +4 -2
  12. package/dist/engine.cjs.map +1 -1
  13. package/dist/engine.js +3 -3
  14. package/dist/index.cjs +119 -23
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +3 -8
  17. package/dist/index.d.ts +3 -8
  18. package/dist/index.js +13 -32
  19. package/dist/index.js.map +1 -1
  20. package/dist/registry/index.d.cts +2 -2
  21. package/dist/registry/index.d.ts +2 -2
  22. package/dist/registry.cjs +110 -2
  23. package/dist/registry.cjs.map +1 -1
  24. package/dist/registry.js +3 -3
  25. package/dist/runtime.cjs +4 -2
  26. package/dist/runtime.cjs.map +1 -1
  27. package/dist/runtime.js +3 -3
  28. package/dist/schema.cjs.map +1 -1
  29. package/dist/schema.js +2 -2
  30. package/dist/styles.css +60 -0
  31. package/dist/styles.css.map +1 -1
  32. package/dist/{types-DwRpXXNy.d.ts → types-BGtR3k9J.d.ts} +1 -1
  33. package/dist/{types-BekE5JTG.d.cts → types-B_pxRqfw.d.cts} +1 -1
  34. package/dist/ux.cjs.map +1 -1
  35. package/dist/ux.d.cts +1 -1
  36. package/dist/ux.d.ts +1 -1
  37. package/dist/ux.js +1 -1
  38. package/package.json +1 -1
  39. package/dist/chunk-KDHLKBL2.js.map +0 -1
  40. package/dist/chunk-QAA4CA22.js.map +0 -1
  41. package/dist/chunk-YXRLIV7A.js.map +0 -1
package/dist/ux.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/registry/registry.ts","../src/ux.ts"],"names":["createEffectDispatcher","useMemo"],"mappings":";;;;;;;;AAEA,IAAM,KAAA,uBAAY,GAAA,EAA+C;AAEjE,IAAM,OAAA,uBAAc,GAAA,EAAoB;AACxC,IAAM,SAAA,uBAAgB,GAAA,EAAgB;AAY/B,SAAS,iBACd,UAAA,EACY;AACZ,EAAA,KAAA,CAAM,GAAA,CAAI,UAAA,CAAW,IAAA,EAAM,UAA+C,CAAA;AAC1E,EAAA,KAAA,MAAW,KAAA,IAAS,WAAW,OAAA,IAAW,IAAI,OAAA,CAAQ,GAAA,CAAI,KAAA,EAAO,UAAA,CAAW,IAAI,CAAA;AAChF,EAAA,MAAA,EAAO;AACP,EAAA,OAAO,MAAM;AACX,IAAA,IAAI,KAAA,CAAM,GAAA,CAAI,UAAA,CAAW,IAAI,MAAO,UAAA,EAAoB;AACtD,MAAA,KAAA,CAAM,MAAA,CAAO,WAAW,IAAI,CAAA;AAC5B,MAAA,KAAA,MAAW,KAAA,IAAS,UAAA,CAAW,OAAA,IAAW,EAAC,EAAG;AAC5C,QAAA,IAAI,OAAA,CAAQ,IAAI,KAAK,CAAA,KAAM,WAAW,IAAA,EAAM,OAAA,CAAQ,OAAO,KAAK,CAAA;AAAA,MAClE;AACA,MAAA,MAAA,EAAO;AAAA,IACT;AAAA,EACF,CAAA;AACF;AAuCA,SAAS,MAAA,GAAe;AACtB,EAAA,KAAA,MAAW,CAAA,IAAK,WAAW,CAAA,EAAE;AAC/B;;;ACAA,IAAM,cAAA,GAAiB,CAAC,IAAA,KAAiB,CAAA,GAAA,EAAM,IAAI,CAAA,CAAA;AAG5C,SAAS,mBAAmB,OAAA,EAA4C;AAC7E,EAAA,MAAM;AAAA,IACJ,OAAA;AAAA,IACA,OAAO,EAAC;AAAA,IACR,KAAA,GAAQ,EAAE,EAAA,EAAI,MAAA,EAAQ,QAAQ,MAAA,EAAO;AAAA,IACrC,OAAA,GAAU;AAAA,GACZ,GAAI,OAAA;AAEJ,EAAA,MAAM,aAAaA,sCAAA,CAAuB,OAAA,EAAS,EAAE,KAAA,EAAO,UAAA,EAAY,MAAM,CAAA;AAE9E,EAAA,MAAM,YAA8B,EAAC;AACrC,EAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,EAAG;AACvC,IAAA,SAAA,CAAU,QAAQ,IAAI,CAAC,IAAI,OAAO,EAAE,MAAK,KAA0B;AACjE,MAAA,MAAM,MAAA,GAAU,IAAA,CAAK,IAAA,EAA2D,MAAA,IAAU,EAAC;AAC3F,MAAA,MAAM,MAAA,GAAS,MAAM,UAAA,CAAW,QAAA,CAAS,MAAM,MAAM,CAAA;AAKrD,MAAA,IAAI,UAAU,OAAO,MAAA,KAAW,aAAa,QAAA,IAAY,MAAA,IAAU,YAAY,MAAA,CAAA,EAAS;AACtF,QAAA,OAAO,MAAA;AAAA,MACT;AACA,MAAA,OAAO,EAAE,MAAA,EAAQ,IAAA,EAAM,MAAA,EAAO;AAAA,IAChC,CAAA;AAAA,EACF;AAEA,EAAA,MAAM,gBAAgB,MAAM;AAC1B,IAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,EAAG;AACvC,MAAA,MAAM,CAAA,GAAI,IAAA,CAAK,IAAI,CAAA,IAAK,EAAC;AACzB,MAAA,gBAAA,CAAiB;AAAA,QACf,IAAA,EAAM,QAAQ,IAAI,CAAA;AAAA,QAClB,QAAA,EAAU,EAAE,QAAA,IAAY,QAAA;AAAA,QACxB,KAAA,EAAO,EAAE,KAAA,IAAS,IAAA;AAAA,QAClB,WAAA,EAAa,CAAA,CAAE,WAAA,IAAe,CAAA,uBAAA,EAA0B,IAAI,CAAA,CAAA,CAAA;AAAA,QAC5D,IAAA,EAAM,EAAE,IAAA,IAAQ,QAAA;AAAA,QAChB,MAAA,EAAQ,EAAE,MAAA,IAAU,SAAA;AAAA,QACpB,MAAA,EAAQ,CAAC,EAAE,EAAA,EAAI,MAAM,CAAA;AAAA,QACrB,SAAS,EAAC;AAAA,QACV,cAAc,CAAA,CAAE;AAAA,OACjB,CAAA;AAAA,IACH;AAAA,EACF,CAAA;AAEA,EAAA,OAAO;AAAA,IACL,SAAA;AAAA,IACA,UAAU,UAAA,CAAW,QAAA;AAAA,IACrB,aAAa,UAAA,CAAW,KAAA;AAAA,IACxB;AAAA,GACF;AACF;AAMO,SAAS,gBAAgB,OAAA,EAA4C;AAC1E,EAAA,MAAM,MAAM,CAAA,EAAG,MAAA,CAAO,IAAA,CAAK,OAAA,CAAQ,OAAO,CAAA,CAAE,IAAA,EAAK,CAAE,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA,EAAI,OAAA,CAAQ,KAAA,EAAO,MAAM,MAAM,CAAA,CAAA;AAE3F,EAAA,OAAOC,cAAQ,MAAM,kBAAA,CAAmB,OAAO,CAAA,EAAG,CAAC,GAAG,CAAC,CAAA;AACzD","file":"ux.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","/**\n * FlowRunnerUx — the **flow-driven UX** bridge. The headless counterpart to\n * agent-integrations: where that wires an *agent* to host UI surfaces, this\n * wires a *running flow* to host UX. Both share the same primitives from\n * `@particle-academy/fancy-auto-common` (activity bus, effect dispatch).\n *\n * The host registers named UX effects (toast, navigate, confirm, …); this turns\n * each into a flow executor keyed by a node kind (`ux_<effect>` by default), so\n * dropping a `ux_toast` node into a `<FlowEditor>` and running it fires the\n * host's toast. Every dispatch broadcasts an `AutoActivityEvent` (source:\"flow\")\n * for presence / logging. Human-in-the-loop is free: an effect that returns a\n * Promise (e.g. an approval dialog) pauses the run until the user resolves it.\n *\n * const ux = createFlowRunnerUx({\n * effects: {\n * toast: ({ message }) => toast({ title: message }),\n * navigate:({ to }) => router.visit(to),\n * confirm: ({ prompt }) => new Promise(res => openDialog(prompt, res)), // pauses the run\n * },\n * });\n * ux.registerKinds(); // adds ux_toast / ux_navigate / ux_confirm to the palette\n * <FlowEditor initial={graph} executors={ux.executors} />\n */\nimport { useMemo } from \"react\";\nimport {\n createEffectDispatcher,\n type DispatchActor,\n type EffectRegistry,\n} from \"@particle-academy/fancy-auto-common\";\nimport { registerNodeKind } from \"./registry/registry\";\nimport type { ConfigField, NodeCategory } from \"./registry/types\";\nimport type { ExecutorRegistry, FlowNode } from \"./types\";\n\nexport type { AutoActivityEvent } from \"@particle-academy/fancy-auto-common\";\n\n/** Per-effect presentation for the palette node kind that drives it. */\nexport type UxEffectMeta = {\n /** Palette label. Default: the effect name. */\n label?: string;\n /** One-line palette description. */\n description?: string;\n /** Emoji / glyph for the node header. */\n icon?: string;\n /** Header accent color. */\n accent?: string;\n /** Palette grouping. Default \"output\". */\n category?: NodeCategory;\n /** Config form fields = the effect's params. */\n configSchema?: ConfigField[];\n};\n\nexport type FlowRunnerUxOptions = {\n /** Named host UX effects the flow can invoke. */\n effects: EffectRegistry;\n /** Optional per-effect palette metadata (used by `registerKinds`). */\n meta?: Record<string, UxEffectMeta>;\n /** Identifies the flow run in emitted activity. Default `{ id: \"flow\", source: \"flow\" }`. */\n actor?: DispatchActor;\n /** Map an effect name to its node-kind name. Default `ux_<effect>`. */\n kindFor?: (effectName: string) => string;\n};\n\nexport type FlowRunnerUx = {\n /** Executor registry to hand to `<FlowEditor executors>` or `runFlow`. */\n executors: ExecutorRegistry;\n /** Invoke an effect imperatively (also emits activity). */\n dispatch: <R = unknown>(name: string, params?: unknown) => Promise<R>;\n /** All effect names. */\n effectNames: () => string[];\n /** Register a palette node kind per effect (`ux_<effect>`). Idempotent. */\n registerKinds: () => void;\n};\n\nconst defaultKindFor = (name: string) => `ux_${name}`;\n\n/** Build a FlowRunnerUx from a set of host effects. Framework-agnostic. */\nexport function createFlowRunnerUx(options: FlowRunnerUxOptions): FlowRunnerUx {\n const {\n effects,\n meta = {},\n actor = { id: \"flow\", source: \"flow\" },\n kindFor = defaultKindFor,\n } = options;\n\n const dispatcher = createEffectDispatcher(effects, { actor, targetKind: \"ux\" });\n\n const executors: ExecutorRegistry = {};\n for (const name of Object.keys(effects)) {\n executors[kindFor(name)] = async ({ node }: { node: FlowNode }) => {\n const params = (node.data as { config?: Record<string, unknown> } | undefined)?.config ?? {};\n const result = await dispatcher.dispatch(name, params);\n // A UX effect can drive flow control: if it returns the decision sugar\n // (`{ branch }` or `{ __port }`) — e.g. an interactive \"choose\" effect that\n // awaits a human pick and returns the chosen port — pass it straight\n // through so runFlow routes on it. Otherwise wrap the result for the feed.\n if (result && typeof result === \"object\" && (\"branch\" in result || \"__port\" in result)) {\n return result;\n }\n return { effect: name, result };\n };\n }\n\n const registerKinds = () => {\n for (const name of Object.keys(effects)) {\n const m = meta[name] ?? {};\n registerNodeKind({\n name: kindFor(name),\n category: m.category ?? \"output\",\n label: m.label ?? name,\n description: m.description ?? `Flow-driven UX effect: ${name}.`,\n icon: m.icon ?? \"✨\",\n accent: m.accent ?? \"#8b5cf6\",\n inputs: [{ id: \"in\" }],\n outputs: [],\n configSchema: m.configSchema,\n });\n }\n };\n\n return {\n executors,\n dispatch: dispatcher.dispatch as FlowRunnerUx[\"dispatch\"],\n effectNames: dispatcher.names,\n registerKinds,\n };\n}\n\n/**\n * React hook form — memoizes on the effect-name set + actor id so the returned\n * executors keep a stable identity across renders.\n */\nexport function useFlowRunnerUx(options: FlowRunnerUxOptions): FlowRunnerUx {\n const key = `${Object.keys(options.effects).sort().join(\",\")}|${options.actor?.id ?? \"flow\"}`;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n return useMemo(() => createFlowRunnerUx(options), [key]);\n}\n"]}
1
+ {"version":3,"sources":["../src/registry/registry.ts","../src/ux.ts"],"names":["createEffectDispatcher","useMemo"],"mappings":"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","file":"ux.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 case \"annotation\": return \"#eab308\";\n default: return \"#71717a\";\n }\n}\n","/**\n * FlowRunnerUx — the **flow-driven UX** bridge. The headless counterpart to\n * agent-integrations: where that wires an *agent* to host UI surfaces, this\n * wires a *running flow* to host UX. Both share the same primitives from\n * `@particle-academy/fancy-auto-common` (activity bus, effect dispatch).\n *\n * The host registers named UX effects (toast, navigate, confirm, …); this turns\n * each into a flow executor keyed by a node kind (`ux_<effect>` by default), so\n * dropping a `ux_toast` node into a `<FlowEditor>` and running it fires the\n * host's toast. Every dispatch broadcasts an `AutoActivityEvent` (source:\"flow\")\n * for presence / logging. Human-in-the-loop is free: an effect that returns a\n * Promise (e.g. an approval dialog) pauses the run until the user resolves it.\n *\n * const ux = createFlowRunnerUx({\n * effects: {\n * toast: ({ message }) => toast({ title: message }),\n * navigate:({ to }) => router.visit(to),\n * confirm: ({ prompt }) => new Promise(res => openDialog(prompt, res)), // pauses the run\n * },\n * });\n * ux.registerKinds(); // adds ux_toast / ux_navigate / ux_confirm to the palette\n * <FlowEditor initial={graph} executors={ux.executors} />\n */\nimport { useMemo } from \"react\";\nimport {\n createEffectDispatcher,\n type DispatchActor,\n type EffectRegistry,\n} from \"@particle-academy/fancy-auto-common\";\nimport { registerNodeKind } from \"./registry/registry\";\nimport type { ConfigField, NodeCategory } from \"./registry/types\";\nimport type { ExecutorRegistry, FlowNode } from \"./types\";\n\nexport type { AutoActivityEvent } from \"@particle-academy/fancy-auto-common\";\n\n/** Per-effect presentation for the palette node kind that drives it. */\nexport type UxEffectMeta = {\n /** Palette label. Default: the effect name. */\n label?: string;\n /** One-line palette description. */\n description?: string;\n /** Emoji / glyph for the node header. */\n icon?: string;\n /** Header accent color. */\n accent?: string;\n /** Palette grouping. Default \"output\". */\n category?: NodeCategory;\n /** Config form fields = the effect's params. */\n configSchema?: ConfigField[];\n};\n\nexport type FlowRunnerUxOptions = {\n /** Named host UX effects the flow can invoke. */\n effects: EffectRegistry;\n /** Optional per-effect palette metadata (used by `registerKinds`). */\n meta?: Record<string, UxEffectMeta>;\n /** Identifies the flow run in emitted activity. Default `{ id: \"flow\", source: \"flow\" }`. */\n actor?: DispatchActor;\n /** Map an effect name to its node-kind name. Default `ux_<effect>`. */\n kindFor?: (effectName: string) => string;\n};\n\nexport type FlowRunnerUx = {\n /** Executor registry to hand to `<FlowEditor executors>` or `runFlow`. */\n executors: ExecutorRegistry;\n /** Invoke an effect imperatively (also emits activity). */\n dispatch: <R = unknown>(name: string, params?: unknown) => Promise<R>;\n /** All effect names. */\n effectNames: () => string[];\n /** Register a palette node kind per effect (`ux_<effect>`). Idempotent. */\n registerKinds: () => void;\n};\n\nconst defaultKindFor = (name: string) => `ux_${name}`;\n\n/** Build a FlowRunnerUx from a set of host effects. Framework-agnostic. */\nexport function createFlowRunnerUx(options: FlowRunnerUxOptions): FlowRunnerUx {\n const {\n effects,\n meta = {},\n actor = { id: \"flow\", source: \"flow\" },\n kindFor = defaultKindFor,\n } = options;\n\n const dispatcher = createEffectDispatcher(effects, { actor, targetKind: \"ux\" });\n\n const executors: ExecutorRegistry = {};\n for (const name of Object.keys(effects)) {\n executors[kindFor(name)] = async ({ node }: { node: FlowNode }) => {\n const params = (node.data as { config?: Record<string, unknown> } | undefined)?.config ?? {};\n const result = await dispatcher.dispatch(name, params);\n // A UX effect can drive flow control: if it returns the decision sugar\n // (`{ branch }` or `{ __port }`) — e.g. an interactive \"choose\" effect that\n // awaits a human pick and returns the chosen port — pass it straight\n // through so runFlow routes on it. Otherwise wrap the result for the feed.\n if (result && typeof result === \"object\" && (\"branch\" in result || \"__port\" in result)) {\n return result;\n }\n return { effect: name, result };\n };\n }\n\n const registerKinds = () => {\n for (const name of Object.keys(effects)) {\n const m = meta[name] ?? {};\n registerNodeKind({\n name: kindFor(name),\n category: m.category ?? \"output\",\n label: m.label ?? name,\n description: m.description ?? `Flow-driven UX effect: ${name}.`,\n icon: m.icon ?? \"✨\",\n accent: m.accent ?? \"#8b5cf6\",\n inputs: [{ id: \"in\" }],\n outputs: [],\n configSchema: m.configSchema,\n });\n }\n };\n\n return {\n executors,\n dispatch: dispatcher.dispatch as FlowRunnerUx[\"dispatch\"],\n effectNames: dispatcher.names,\n registerKinds,\n };\n}\n\n/**\n * React hook form — memoizes on the effect-name set + actor id so the returned\n * executors keep a stable identity across renders.\n */\nexport function useFlowRunnerUx(options: FlowRunnerUxOptions): FlowRunnerUx {\n const key = `${Object.keys(options.effects).sort().join(\",\")}|${options.actor?.id ?? \"flow\"}`;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n return useMemo(() => createFlowRunnerUx(options), [key]);\n}\n"]}
package/dist/ux.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { EffectRegistry, DispatchActor } from '@particle-academy/fancy-auto-common';
2
2
  export { AutoActivityEvent } from '@particle-academy/fancy-auto-common';
3
- import { N as NodeCategory, C as ConfigField } from './types-BekE5JTG.cjs';
3
+ import { N as NodeCategory, C as ConfigField } from './types-B_pxRqfw.cjs';
4
4
  import { E as ExecutorRegistry } from './types-CMSrWVYM.cjs';
5
5
  import 'react';
6
6
  import '@xyflow/react';
package/dist/ux.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { EffectRegistry, DispatchActor } from '@particle-academy/fancy-auto-common';
2
2
  export { AutoActivityEvent } from '@particle-academy/fancy-auto-common';
3
- import { N as NodeCategory, C as ConfigField } from './types-DwRpXXNy.js';
3
+ import { N as NodeCategory, C as ConfigField } from './types-BGtR3k9J.js';
4
4
  import { E as ExecutorRegistry } from './types-CMSrWVYM.js';
5
5
  import 'react';
6
6
  import '@xyflow/react';
package/dist/ux.js CHANGED
@@ -1,4 +1,4 @@
1
- import { registerNodeKind } from './chunk-YXRLIV7A.js';
1
+ import { registerNodeKind } from './chunk-Q6IPK64P.js';
2
2
  import { useMemo } from 'react';
3
3
  import { createEffectDispatcher } from '@particle-academy/fancy-auto-common';
4
4
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@particle-academy/fancy-flow",
3
- "version": "0.24.0",
3
+ "version": "0.25.0",
4
4
  "description": "Workflow editor + runner. Six built-in node kits (trigger / action / decision / output / note / subgraph), tokenized theme, topological execution with per-node status. React-flow bundled; consumers npm install fancy-flow and get nothing extra.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/runtime/run-flow.ts"],"names":[],"mappings":"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","file":"chunk-KDHLKBL2.js","sourcesContent":["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"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/registry/connection.ts","../src/registry/subflow.ts","../src/registry/llm-router.ts","../src/registry/RegistryNode.tsx","../src/components/nodes/LaneNode.tsx","../src/registry/builtin.ts","../src/registry/index.ts"],"names":["jsxs","jsx","memo"],"mappings":"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","file":"chunk-QAA4CA22.js","sourcesContent":["import type { Connection, Edge } from \"@xyflow/react\";\nimport type { FlowNode, PortDescriptor } from \"../types\";\nimport { getNodeKind } from \"./registry\";\nimport { resolveNodePorts } from \"./ports\";\n\n/**\n * Connection validation — the single rule that decides whether an edge between\n * two ports is allowed. Lives here (React-free, registry-adjacent) so BOTH the\n * canvas (`<FlowCanvas isValidConnection>`) and the agent bridge's\n * `flow_connect` tool call the same function: a connection the canvas refuses\n * is a connection an agent cannot sneak past, and vice versa — no drift.\n *\n * `PortDescriptor.type` has always documented itself as being \"for hosts that\n * want to validate connections\", but nothing consumed it. This wires it up.\n */\n\n/**\n * Wildcard port type — matches any other type. A port that declares no `type`\n * is treated as a wildcard too, so existing flows (whose ports are untyped)\n * validate exactly as before.\n */\nexport const ANY_PORT_TYPE = \"any\";\n\n/** Decides whether a source-output port may feed a target-input port. */\nexport type PortCompatibility = (\n source: PortDescriptor | undefined,\n target: PortDescriptor | undefined,\n) => boolean;\n\n/**\n * Default compatibility rule: allow the connection UNLESS both ports declare a\n * concrete, differing type. An absent type or the `any` wildcard matches\n * anything — so typed ports get enforced while untyped ports stay permissive,\n * making this a safe default that never breaks an existing untyped graph.\n */\nexport const defaultPortCompatibility: PortCompatibility = (source, target) => {\n const s = source?.type;\n const t = target?.type;\n if (!s || !t) return true;\n if (s === ANY_PORT_TYPE || t === ANY_PORT_TYPE) return true;\n return s === t;\n};\n\nexport type ConnectionValidatorOptions = {\n /** Override the type-compatibility rule. Defaults to {@link defaultPortCompatibility}. */\n compatible?: PortCompatibility;\n /**\n * Allow a node's own output to feed its own input (a self-loop). Default\n * false — self-connections are almost always an accident, and the rare flow\n * that wants one can opt in.\n */\n allowSelfConnection?: boolean;\n};\n\n/** Resolve a node's effective ports for one side, going through the registry. */\nfunction portsFor(node: FlowNode, side: \"inputs\" | \"outputs\"): PortDescriptor[] {\n const kind = getNodeKind((node.data as any)?.kind ?? node.type);\n const resolved = resolveNodePorts(node, kind ?? undefined);\n return resolved[side] ?? [];\n}\n\n/**\n * Resolve which port a handle id refers to. When a side has a single port and\n * the handle id is absent (React Flow omits it for a lone default handle), use\n * that port; otherwise match by id.\n */\nfunction findPort(\n ports: PortDescriptor[],\n handleId: string | null | undefined,\n): PortDescriptor | undefined {\n if (handleId == null) return ports.length === 1 ? ports[0] : undefined;\n return ports.find((p) => p.id === handleId);\n}\n\n/**\n * Build an `isValidConnection` predicate that enforces port-type compatibility\n * against a live node list. Pass it straight to `<FlowCanvas isValidConnection>`\n * or reuse it to gate an agent's `flow_connect`.\n *\n * `getNodes` is called on every check so the validator always sees the current\n * graph (wire it to a ref/state getter, not a snapshot).\n *\n * A connection is rejected when: an endpoint is missing; it is a self-loop and\n * `allowSelfConnection` is off; either node is unknown; or the resolved ports\n * are type-incompatible. Nodes/ports with no declared type validate as before.\n */\nexport function createConnectionValidator(\n getNodes: () => FlowNode[],\n options: ConnectionValidatorOptions = {},\n): (connection: Connection | Edge) => boolean {\n const compatible = options.compatible ?? defaultPortCompatibility;\n return (connection) => {\n const { source, target, sourceHandle, targetHandle } = connection;\n if (!source || !target) return false;\n if (!options.allowSelfConnection && source === target) return false;\n\n const nodes = getNodes();\n const src = nodes.find((n) => n.id === source);\n const tgt = nodes.find((n) => n.id === target);\n if (!src || !tgt) return false;\n\n const outPort = findPort(portsFor(src, \"outputs\"), sourceHandle);\n const inPort = findPort(portsFor(tgt, \"inputs\"), targetHandle);\n return compatible(outPort, inPort);\n };\n}\n","import { getWorkflowResolver, isResolutionFailure } from \"./capabilities\";\nimport { runFlow } from \"../runtime/run-flow\";\nimport type { NodeExecutor, RunEvent } from \"../types\";\n\n/**\n * `@fancy/subflow` — run another workflow and bring its result home.\n *\n * Core, not marketplace: it introduces no third-party dependency. It runs a\n * child graph through the very same engine, so the only thing it needs from the\n * host is where workflows live (`registerWorkflowResolver`).\n *\n * Three output modes, because both halves are genuinely useful:\n *\n * - `output` — the child's outputs arrive on `out` when it finishes.\n * - `stream` — the child's events are forwarded live on `stream` as they\n * happen, so a parent can show progress instead of a spinner.\n * - `both` — stream while running AND deliver the final outputs.\n *\n * Recursion is guarded by depth. A workflow that references itself (directly or\n * through a chain) would otherwise recurse until the stack dies, which surfaces\n * as an opaque crash rather than \"you built a loop\".\n */\n\nexport const DEFAULT_MAX_DEPTH = 8;\n\nexport type SubflowMode = \"output\" | \"stream\" | \"both\";\n\nexport function subflowMode(config: Record<string, unknown>): SubflowMode {\n const mode = config.mode;\n return mode === \"stream\" || mode === \"both\" ? mode : \"output\";\n}\n\n/** Ports follow the mode — `stream` only exists when something streams. */\nexport function subflowPorts(config: Record<string, unknown>) {\n const mode = subflowMode(config);\n const ports = [{ id: \"out\", label: \"result\" }];\n if (mode === \"stream\" || mode === \"both\") ports.unshift({ id: \"stream\", label: \"stream\" });\n return ports;\n}\n\nexport const subflowExecutor: NodeExecutor = async (ctx) => {\n const config = ((ctx.node.data as any)?.config ?? {}) as Record<string, unknown>;\n const ref = String(config.workflow ?? \"\").trim();\n if (!ref) ctx.abort(\"subflow has no workflow reference configured\");\n\n const resolver = getWorkflowResolver();\n if (!resolver) {\n ctx.abort(\n \"No workflow resolver registered. Call registerWorkflowResolver() so subflow can find the workflow it references.\",\n );\n }\n\n const maxDepth = Number.isFinite(config.maxDepth) ? Number(config.maxDepth) : DEFAULT_MAX_DEPTH;\n const depth = ctx.depth ?? 0;\n if (depth + 1 > maxDepth) {\n // Name the cause. \"Maximum call stack exceeded\" tells an author nothing\n // about the workflow they wired into itself.\n ctx.abort(\n `subflow depth limit reached (${maxDepth}) at \"${ref}\" — a workflow is referencing itself, directly or through a chain.`,\n );\n }\n\n // An optional pin. A workflow another workflow depends on is an interface:\n // without a pin, someone edits the child and the parent silently runs\n // different logic while still reporting success.\n const pinned = config.version === undefined || config.version === \"\" ? undefined : Number(config.version);\n if (pinned !== undefined && !Number.isInteger(pinned)) {\n ctx.abort(`subflow \"${ref}\" has a non-integer version pin (${String(config.version)}).`);\n }\n\n const resolved = await resolver!(ref, pinned);\n\n // A mismatch names BOTH versions. Reporting it as \"not found\" would send an\n // author looking for a workflow that is sitting right there — which is why\n // the resolver can say which of the two failures it hit.\n const child = isResolutionFailure(resolved)\n ? ctx.abort(\n resolved.reason === \"version-mismatch\"\n ? (resolved.message ??\n `subflow \"${ref}\" is pinned to version ${pinned}, but the host has ${resolved.available ?? \"a different version\"}.`)\n : (resolved.message ?? `subflow could not resolve workflow \"${ref}\"`),\n )\n : resolved;\n\n if (!child) ctx.abort(`subflow could not resolve workflow \"${ref}\"`);\n\n const mode = subflowMode(config);\n const streaming = mode === \"stream\" || mode === \"both\";\n\n const forward = (event: RunEvent) => {\n if (!streaming) return;\n // Surface the child's progress on the PARENT's feed as a log line against\n // this node. Re-emitting the child's raw events would collide with the\n // parent's own node ids — a child's \"node-status\" for its `output` node is\n // not a status for anything in the parent graph.\n const detail =\n event.type === \"node-status\"\n ? `${event.nodeId} ${event.status}`\n : event.type === \"run-end\"\n ? `finished (${event.ok ? \"ok\" : \"failed\"})`\n : event.type;\n ctx.emit({\n type: \"log\",\n nodeId: ctx.node.id,\n level: \"info\",\n message: `[${ref}] ${detail}`,\n });\n };\n\n const result = await runFlow(\n child!,\n (config.executors as never) ?? {},\n forward,\n {\n initialInputs: (config.inputs as Record<string, Record<string, unknown>>) ?? {\n // With no explicit mapping, hand the parent's inputs to the child's\n // entry points — the obvious default, and it makes the simple case\n // require no configuration at all.\n __parent: ctx.inputs as Record<string, unknown>,\n },\n depth: depth + 1,\n },\n );\n\n if (!result.ok) {\n ctx.abort(`subflow \"${ref}\" failed: ${result.error ?? \"unknown error\"}`);\n }\n\n // `stream` alone still emits a final value on `stream` so downstream nodes\n // have something to run on; `both` publishes on every declared port.\n if (mode === \"stream\") {\n return { __port: \"stream\", value: result.outputs };\n }\n if (mode === \"both\") {\n return result.outputs;\n }\n return { __port: \"out\", value: result.outputs };\n};\n","import { getLlmClient, type LlmRoute } from \"./capabilities\";\nimport type { NodeExecutor } from \"../types\";\n\n/**\n * `@fancy/llm_branch` — a SHUTTLE, not an engine.\n *\n * It carries the declared routes and the decision prompt out to whatever LLM\n * client the host registered, and carries the chosen port back down the graph.\n * It contains no provider SDK, no prompt engineering, no response parsing and\n * no retry policy — all of that belongs to the host's client, which is what\n * lets this node live in core without every consumer inheriting an LLM\n * dependency.\n *\n * The one thing it does own is graph integrity, because that is a workflow\n * concern rather than an AI one: a port the model invents must never route.\n */\n\n/** Read the node's declared routes out of config. */\nexport function declaredRoutes(config: Record<string, unknown>): LlmRoute[] {\n const raw = config.routes;\n if (!Array.isArray(raw)) return [];\n return raw\n .map((r) => ({ port: String((r as any)?.port ?? \"\").trim(), description: (r as any)?.description }))\n .filter((r) => r.port !== \"\");\n}\n\n/**\n * Where a run goes when the model returns a port that was never offered.\n *\n * Emitting on a port with no edge silently ends the branch — the worst failure\n * mode in a workflow engine, because the run reports success having done\n * nothing. So: the `fallback` port when it exists, else the first declared\n * route, and always loudly.\n */\nexport function resolveFallbackPort(routes: LlmRoute[], fallbackEnabled: boolean): string {\n if (fallbackEnabled) return \"fallback\";\n // Callers only reach this with at least one declared route (a node with none\n // aborts earlier), so there is always somewhere safe to land.\n return routes[0]?.port ?? \"out\";\n}\n\nexport const llmRouterExecutor: NodeExecutor = async (ctx) => {\n const config = ((ctx.node.data as any)?.config ?? {}) as Record<string, unknown>;\n const routes = declaredRoutes(config);\n\n if (routes.length === 0) {\n ctx.abort(\"llm_router has no routes configured\");\n }\n\n const client = getLlmClient();\n if (!client) {\n // Fail loudly rather than guessing a branch. A silent default here would\n // look like the model made a choice.\n ctx.abort(\n \"No LLM client registered. Call registerLlmClient() with your provider adapter — fancy-flow ships the routing, not the model call.\",\n );\n }\n\n const fallbackEnabled = config.fallback !== false;\n\n const choice = await client!.chooseRoute({\n system: typeof config.system === \"string\" ? config.system : undefined,\n prompt: String(config.prompt ?? ctx.inputs ?? \"\"),\n routes,\n provider: typeof config.provider === \"string\" ? config.provider : undefined,\n model: typeof config.model === \"string\" ? config.model : undefined,\n credential: typeof config.credential === \"string\" ? config.credential : undefined,\n });\n\n const offered = new Set(routes.map((r) => r.port));\n let port = choice?.port ?? \"\";\n let reason = choice?.reason;\n\n if (!offered.has(port)) {\n const safe = resolveFallbackPort(routes, fallbackEnabled);\n ctx.emit({\n type: \"log\",\n nodeId: ctx.node.id,\n level: \"warn\",\n message: `llm_router: model returned \"${port || \"(nothing)\"}\", which is not a declared route. Routing to \"${safe}\".`,\n });\n reason = reason ?? `unrecognised route \"${port}\"`;\n port = safe;\n }\n\n // The reason travels WITH the value, so a completed run explains itself\n // without needing the model call replayed.\n return { __port: port, value: { route: port, reason, input: ctx.inputs } };\n};\n","import { memo, useMemo } from \"react\";\nimport { Handle, NodeResizer, NodeToolbar, Position, type NodeProps } from \"@xyflow/react\";\nimport type { FlowNode, NodeRunStatus, PortDescriptor } from \"../types\";\nimport { categoryAccent, getNodeKind } from \"./registry\";\nimport { nodeConfig, resolveNodePorts } from \"./ports\";\n\n/**\n * RegistryNode — generic node renderer that looks up the node's kind in\n * the registry and applies its `accent`/`label`/`icon`/`renderBody`. Used\n * as the xyflow node component for every registered kind.\n */\nfunction RegistryNodeInner(props: NodeProps<FlowNode>) {\n const kindName = (props.data as any).kind ?? props.type;\n const kind = useMemo(() => getNodeKind(kindName), [kindName]);\n\n if (!kind) {\n return (\n <div className=\"ff-node ff-node--unknown\">\n <div className=\"ff-node__header\" style={{ background: \"#71717a\" }}>\n <span className=\"ff-node__tag\">UNKNOWN</span>\n <span className=\"ff-node__label\">{kindName}</span>\n </div>\n <p className=\"ff-node__desc\">No registered kind for \"{kindName}\".</p>\n </div>\n );\n }\n\n const data = props.data;\n const status: NodeRunStatus = data.status ?? \"idle\";\n const accent = kind.accent ?? categoryAccent(kind.category);\n const resolved = resolveNodePorts(props, kind);\n const inputs: PortDescriptor[] = resolved.inputs ?? defaultInputs(kind.category);\n const outputs: PortDescriptor[] = resolved.outputs ?? defaultOutputs(kind.category);\n const config = nodeConfig(props);\n const label = data.label ?? kind.label;\n\n return (\n <div\n className={[\n \"ff-node\",\n `ff-node--status-${status}`,\n `ff-node--cat-${kind.category}`,\n props.selected ? \"ff-node--selected\" : \"\",\n kind.resizable ? \"ff-node--resizable\" : \"\",\n ].filter(Boolean).join(\" \")}\n style={{ borderColor: props.selected ? accent : undefined }}\n >\n {kind.resizable && (\n <NodeResizer\n isVisible={props.selected ?? false}\n color={accent}\n {...(typeof kind.resizable === \"object\" ? kind.resizable : {})}\n />\n )}\n {kind.toolbar && (\n <NodeToolbar isVisible={props.selected ?? false}>\n {kind.toolbar({ nodeId: props.id, config: config as any, selected: props.selected ?? false })}\n </NodeToolbar>\n )}\n <header className=\"ff-node__header\" style={{ background: accent }}>\n {kind.icon && <span className=\"ff-node__icon\" aria-hidden>{kind.icon}</span>}\n <span className=\"ff-node__tag\">{kind.label.toUpperCase()}</span>\n <span className=\"ff-node__label\">{label}</span>\n {status !== \"idle\" && <span className={`ff-node__dot ff-node__dot--${status}`} aria-label={`status ${status}`} />}\n </header>\n\n {data.description && <p className=\"ff-node__desc\">{data.description}</p>}\n\n <div className=\"ff-node__body\">\n {kind.renderBody\n ? kind.renderBody({ nodeId: props.id, config: config as any, selected: props.selected ?? false })\n : <DefaultBody config={config} kind={kind.configSchema} />}\n </div>\n\n {data.statusText && <p className=\"ff-node__status-text\">{data.statusText}</p>}\n\n {(data as any).output !== undefined && (\n <p className=\"ff-node__output\" title=\"Latest output\">→ {previewValue((data as any).output)}</p>\n )}\n\n {inputs.map((p, i) => (\n <Handle\n key={p.id}\n type=\"target\"\n position={Position.Left}\n id={p.id}\n style={portStyle(i, inputs.length)}\n title={p.label ?? p.id}\n />\n ))}\n {outputs.map((p, i) => (\n <Handle\n key={p.id}\n type=\"source\"\n position={Position.Right}\n id={p.id}\n style={portStyle(i, outputs.length)}\n title={p.label ?? p.id}\n />\n ))}\n </div>\n );\n}\n\nexport const RegistryNode = memo(RegistryNodeInner);\n\nfunction defaultInputs(category: string): PortDescriptor[] {\n return category === \"trigger\" ? [] : [{ id: \"in\" }];\n}\nfunction defaultOutputs(category: string): PortDescriptor[] {\n return category === \"output\" ? [] : [{ id: \"out\" }];\n}\n\nfunction portStyle(i: number, total: number): React.CSSProperties {\n if (total <= 1) return {};\n const slot = (100 / (total + 1)) * (i + 1);\n return { top: `${slot}%` };\n}\n\n/**\n * DefaultBody — compact summary of the config values for nodes that\n * don't provide a custom renderBody. Skips fields that look empty.\n */\nfunction DefaultBody({ config, kind }: { config: Record<string, unknown>; kind?: import(\"./types\").ConfigField[] }) {\n const fields = kind ?? [];\n const visible = fields\n .map((f) => ({ field: f, value: config[f.key] }))\n .filter(({ value }) => value !== undefined && value !== \"\" && value !== null);\n if (visible.length === 0) {\n return <div className=\"ff-node__body-empty\">— configure in the panel</div>;\n }\n return (\n <ul className=\"ff-node__summary\">\n {visible.slice(0, 4).map(({ field, value }) => (\n <li key={field.key}>\n <span className=\"ff-node__summary-key\">{field.label}:</span>\n <span className=\"ff-node__summary-value\">{previewValue(value)}</span>\n </li>\n ))}\n {visible.length > 4 && <li className=\"ff-node__summary-more\">+ {visible.length - 4} more</li>}\n </ul>\n );\n}\n\nconst truncate = (s: string, n = 30): string => (s.length > n ? s.slice(0, n - 1) + \"…\" : s);\n\n/** A short, human name for one item in a repeater/list value. */\nfunction itemLabel(item: unknown): string {\n if (item && typeof item === \"object\") {\n const o = item as Record<string, unknown>;\n const name = o.label ?? o.name ?? o.key ?? o.title ?? o.id;\n if (typeof name === \"string\" && name) return name;\n if (typeof name === \"number\") return String(name);\n return \"item\";\n }\n return String(item ?? \"\");\n}\n\n/**\n * A node card's job is to read at a glance, not to be a data dump — so a value\n * is summarised, never `JSON.stringify`d. An array becomes its item names (or a\n * count), an object becomes a field count. Raw JSON on a card was the specific\n * thing to kill: `Fields: [{\"key\":\"answer\",…}]` reads as noise.\n */\nexport function previewValue(v: unknown): string {\n if (v === null || v === undefined) return \"\";\n if (typeof v === \"string\") return truncate(v);\n if (typeof v === \"number\" || typeof v === \"boolean\") return String(v);\n if (Array.isArray(v)) {\n if (v.length === 0) return \"none\";\n const names = v.slice(0, 3).map(itemLabel).filter(Boolean).join(\", \");\n const rest = v.length > 3 ? `, +${v.length - 3}` : \"\";\n return names ? truncate(names + rest) : `${v.length} item${v.length === 1 ? \"\" : \"s\"}`;\n }\n if (typeof v === \"object\") {\n const keys = Object.keys(v as object);\n return keys.length === 0 ? \"empty\" : `${keys.length} field${keys.length === 1 ? \"\" : \"s\"}`;\n }\n return \"…\";\n}\n","import { memo } from \"react\";\nimport { NodeResizer, type NodeProps } from \"@xyflow/react\";\nimport type { FlowNode } from \"../../types\";\nimport { categoryAccent } from \"../../registry/registry\";\n\n/**\n * LaneNode — a resizable swimlane band. A portless container: child nodes are\n * parented into it (`parentId` + `extent:'parent'`) and render on top, so this\n * node is just the titled background. Wired as the `@particle-academy/lane`\n * kind's `component`, so `buildNodeTypes` uses it instead of the default card.\n */\nfunction LaneNodeInner(props: NodeProps<FlowNode>) {\n const data = props.data as any;\n const config = data.config ?? {};\n const title: string = config.title ?? data.label ?? \"Lane\";\n const orientation: string = config.orientation ?? \"horizontal\";\n const accent: string = config.color ?? data.color ?? categoryAccent(\"layout\");\n return (\n <div\n className={[\"ff-lane\", `ff-lane--${orientation}`, props.selected ? \"ff-lane--selected\" : \"\"]\n .filter(Boolean)\n .join(\" \")}\n style={{ borderColor: props.selected ? accent : undefined }}\n >\n <NodeResizer isVisible={props.selected ?? false} color={accent} minWidth={160} minHeight={72} />\n <div className=\"ff-lane__header\" style={{ background: accent }}>\n <span className=\"ff-lane__title\">{title}</span>\n </div>\n </div>\n );\n}\n\nexport const LaneNode = memo(LaneNodeInner);\n","import { createElement } from \"react\";\nimport { registerNodeKind } from \"./registry\";\nimport { RichInputPreview } from \"./rich-input\";\nimport { LaneNode } from \"../components/nodes/LaneNode\";\nimport { llmRouterExecutor } from \"./llm-router\";\nimport { subflowExecutor, subflowPorts, DEFAULT_MAX_DEPTH } from \"./subflow\";\nimport type { PortDescriptor } from \"../types\";\nimport type { ConfigField, NodeKindDefinition } from \"./types\";\n\n/**\n * Built-in agentic node kit. Every kind ships with schema + UI but\n * NO executor — host apps wire executors per kind so they control where\n * memory, data, network, and AI calls actually go.\n */\n\n/**\n * Ports for `switch_case`, derived from its `cases` map (match value → port).\n *\n * Several match values may route to the same port, so ports are de-duplicated\n * and labelled with every value that reaches them (\"a|c\"). `default` is always\n * present — unmatched input has to land somewhere.\n */\nfunction casePorts(cases: unknown): PortDescriptor[] {\n const byPort = new Map<string, string[]>();\n if (cases && typeof cases === \"object\" && !Array.isArray(cases)) {\n for (const [match, port] of Object.entries(cases as Record<string, unknown>)) {\n if (typeof port !== \"string\" || port === \"\" || port === \"default\") continue;\n const matches = byPort.get(port) ?? [];\n matches.push(match);\n byPort.set(port, matches);\n }\n }\n const ports: PortDescriptor[] = [...byPort].map(([id, matches]) => ({\n id,\n label: matches.join(\"|\"),\n }));\n return [...ports, { id: \"default\", label: \"default\" }];\n}\n\n/**\n * Ports for `llm_branch`, derived from its `routes` list. Blank and duplicate\n * port names are dropped so a half-typed route can't collide with a real one.\n */\nfunction routePorts(routes: unknown, fallback?: unknown): PortDescriptor[] {\n const ports: PortDescriptor[] = [];\n const seen = new Set<string>();\n if (Array.isArray(routes)) {\n for (const route of routes) {\n const id = (route as any)?.port;\n if (typeof id !== \"string\" || id.trim() === \"\" || seen.has(id)) continue;\n seen.add(id);\n ports.push({ id, label: id });\n }\n }\n if (fallback !== false && !seen.has(\"fallback\")) {\n ports.push({ id: \"fallback\", label: \"fallback\" });\n }\n if (ports.length === 0) ports.push({ id: \"out\" });\n return ports;\n}\n\nconst HTTP_METHODS: ConfigField[] = [\n { type: \"select\", key: \"method\", label: \"Method\", options: [\n { value: \"GET\", label: \"GET\" },\n { value: \"POST\", label: \"POST\" },\n { value: \"PUT\", label: \"PUT\" },\n { value: \"PATCH\", label: \"PATCH\" },\n { value: \"DELETE\", label: \"DELETE\" },\n ], default: \"GET\", required: true },\n];\n\nconst KINDS: NodeKindDefinition[] = [\n // ───────────── Triggers ─────────────\n {\n name: \"@particle-academy/manual_trigger\",\n aliases: [\"manual_trigger\", \"@fancy/manual_trigger\"],\n category: \"trigger\",\n label: \"Manual\",\n description: \"Entry point fired when the user clicks Run.\",\n icon: \"⚡\",\n inputs: [],\n outputs: [{ id: \"out\" }],\n },\n {\n name: \"@particle-academy/webhook_trigger\",\n aliases: [\"webhook_trigger\", \"@fancy/webhook_trigger\"],\n category: \"trigger\",\n label: \"Webhook\",\n description: \"Triggered by an inbound HTTP request to a host-provided URL.\",\n icon: \"📡\",\n inputs: [],\n outputs: [{ id: \"out\", label: \"payload\" }],\n configSchema: [\n { type: \"text\", key: \"path\", label: \"Path\", placeholder: \"/hooks/my-flow\", required: true },\n { type: \"select\", key: \"method\", label: \"Method\", options: [\n { value: \"POST\", label: \"POST\" }, { value: \"GET\", label: \"GET\" },\n ], default: \"POST\" },\n { type: \"credential\", key: \"secret\", label: \"Verifying secret\", credentialType: \"webhook_secret\" },\n ],\n },\n {\n name: \"@particle-academy/schedule_trigger\",\n aliases: [\"schedule_trigger\", \"@fancy/schedule_trigger\"],\n category: \"trigger\",\n label: \"Schedule\",\n description: \"Fires on a cron schedule (host-implemented).\",\n icon: \"⏱\",\n inputs: [],\n outputs: [{ id: \"out\" }],\n configSchema: [\n { type: \"text\", key: \"cron\", label: \"Cron\", placeholder: \"*/5 * * * *\", required: true,\n description: \"Standard 5-field cron expression.\" },\n { type: \"text\", key: \"timezone\", label: \"Timezone\", placeholder: \"UTC\", default: \"UTC\" },\n ],\n },\n {\n name: \"@particle-academy/user_input\",\n aliases: [\"user_input\", \"@fancy/user_input\"],\n pausesForHuman: \"input\",\n category: \"human\",\n label: \"User Input\",\n description: \"Pause the flow until the user submits the configured form.\",\n icon: \"✎\",\n inputs: [{ id: \"in\" }],\n outputs: [{ id: \"out\", label: \"values\" }],\n configSchema: [\n { type: \"text\", key: \"title\", label: \"Form title\", default: \"Need your input\" },\n {\n type: \"repeater\",\n key: \"fields\",\n label: \"Fields\",\n description: \"The form the run pauses on.\",\n titleKey: \"label\",\n addLabel: \"Add field\",\n minItems: 1,\n fields: [\n { type: \"text\", key: \"key\", label: \"Key\", required: true, placeholder: \"answer\" },\n { type: \"text\", key: \"label\", label: \"Label\", required: true, placeholder: \"Your answer\" },\n {\n type: \"select\", key: \"type\", label: \"Type\", default: \"text\",\n options: [\n { value: \"text\", label: \"Text\" },\n { value: \"textarea\", label: \"Long text\" },\n { value: \"number\", label: \"Number\" },\n { value: \"select\", label: \"Select\" },\n { value: \"switch\", label: \"Switch\" },\n ],\n },\n { type: \"switch\", key: \"required\", label: \"Required\", default: false },\n ],\n default: [{ key: \"answer\", label: \"Your answer\", type: \"textarea\", required: true }],\n },\n ],\n },\n\n {\n name: \"@particle-academy/rich_user_input\",\n aliases: [\"rich_user_input\", \"@fancy/rich_user_input\"],\n pausesForHuman: \"input\",\n category: \"human\",\n label: \"Rich User Input\",\n description: \"Pause the flow on a fully authored page — content, required reading, multi-section forms.\",\n icon: \"▤\",\n inputs: [{ id: \"in\" }],\n outputs: [{ id: \"out\", label: \"values\" }],\n configSchema: [\n { type: \"text\", key: \"title\", label: \"Step title\", default: \"Please review\" },\n {\n type: \"document\",\n key: \"document\",\n label: \"Page content\",\n documentType: \"stages\",\n description: \"Authored with the host's document editor (fancy-cms Stages).\",\n },\n { type: \"switch\", key: \"requireConfirm\", label: \"Require explicit confirmation\", default: true },\n { type: \"text\", key: \"submitLabel\", label: \"Submit button\", default: \"Continue\" },\n ],\n // Preview the authored page inside a FauxClient frame, so the canvas shows\n // what the person hitting this step will actually see.\n renderBody: (ctx) => createElement(RichInputPreview, { config: (ctx.config ?? {}) as Record<string, unknown> }),\n },\n\n {\n name: \"@particle-academy/subflow\",\n aliases: [\"subflow\", \"@fancy/subflow\"],\n category: \"logic\",\n label: \"SubFlow\",\n description: \"Run another workflow and bring its result — or its live progress — back into this one.\",\n icon: \"⧉\",\n inputs: [{ id: \"in\" }],\n // The stream port only exists when something actually streams.\n outputs: (config: any) => subflowPorts(config ?? {}),\n // Core, not marketplace: it runs a child graph through this same engine and\n // needs nothing from outside except where workflows live.\n executor: subflowExecutor,\n configSchema: [\n { type: \"text\", key: \"workflow\", label: \"Workflow\", required: true,\n placeholder: \"onboarding-v2\",\n description: \"Reference resolved by the host's registerWorkflowResolver().\" },\n { type: \"number\", key: \"version\", label: \"Pin to version\",\n description: \"Optional. Leave blank to always run the child's current version. Pinning fails the run loudly if the child has moved on — without it, someone edits the child and this flow silently runs different logic.\" },\n {\n type: \"select\", key: \"mode\", label: \"Return\", default: \"output\",\n options: [\n { value: \"output\", label: \"Output when it finishes\" },\n { value: \"stream\", label: \"Stream progress as it runs\" },\n { value: \"both\", label: \"Both — stream, then output\" },\n ],\n description: \"Streaming adds a second port so a parent can show progress instead of a spinner.\",\n },\n { type: \"keyvalue\", key: \"inputs\", label: \"Input mapping\",\n description: \"Values handed to the child's entry points. Omit to pass this node's inputs straight through.\",\n keyLabel: \"Name\", valueLabel: \"Value\", addLabel: \"Add input\" },\n { type: \"number\", key: \"maxDepth\", label: \"Max nesting depth\", default: DEFAULT_MAX_DEPTH, min: 1, max: 32,\n description: \"Guards against a workflow referencing itself.\" },\n ],\n },\n\n // ───────────── Logic ─────────────\n {\n name: \"@particle-academy/branch\",\n aliases: [\"branch\", \"@fancy/branch\"],\n category: \"logic\",\n label: \"Branch\",\n description: \"Multi-way branch on a condition or value.\",\n icon: \"◇\",\n inputs: [{ id: \"in\" }],\n outputs: [{ id: \"true\", label: \"true\" }, { id: \"false\", label: \"false\" }],\n configSchema: [\n {\n type: \"select\", key: \"match\", label: \"Match\", default: \"all\",\n options: [\n { value: \"all\", label: \"All conditions (AND)\" },\n { value: \"any\", label: \"Any condition (OR)\" },\n ],\n },\n {\n type: \"repeater\",\n key: \"conditions\",\n label: \"Conditions\",\n description: \"Routes to `true` when these match, otherwise `false`.\",\n titleKey: \"left\",\n addLabel: \"Add condition\",\n minItems: 1,\n fields: [\n { type: \"expression\", key: \"left\", label: \"Value\", example: \"{{ $json.status }}\", required: true },\n {\n type: \"select\", key: \"operator\", label: \"Is\", default: \"eq\",\n options: [\n { value: \"eq\", label: \"equal to\" },\n { value: \"neq\", label: \"not equal to\" },\n { value: \"contains\", label: \"contains\" },\n { value: \"not_contains\", label: \"does not contain\" },\n { value: \"gt\", label: \"greater than\" },\n { value: \"gte\", label: \"greater than or equal to\" },\n { value: \"lt\", label: \"less than\" },\n { value: \"lte\", label: \"less than or equal to\" },\n { value: \"truthy\", label: \"true\" },\n { value: \"falsy\", label: \"false\" },\n { value: \"empty\", label: \"empty\" },\n { value: \"not_empty\", label: \"not empty\" },\n ],\n },\n { type: \"text\", key: \"right\", label: \"Compared to\", placeholder: \"active\" },\n ],\n default: [{ left: \"\", operator: \"eq\", right: \"\" }],\n },\n {\n type: \"expression\",\n key: \"condition\",\n label: \"Raw expression (advanced)\",\n example: \"{{ $json.active && $json.score > 10 }}\",\n description: \"Escape hatch for logic the builder can't express. Overrides the conditions above when set.\",\n },\n ],\n },\n {\n name: \"@particle-academy/switch_case\",\n aliases: [\"switch_case\", \"@fancy/switch_case\"],\n category: \"logic\",\n label: \"Switch\",\n description: \"Route to one of N labelled outputs based on a key.\",\n icon: \"⤳\",\n inputs: [{ id: \"in\" }],\n // Ports ARE the config: every distinct port a case routes to becomes an\n // output handle, plus the always-present `default`. Editing the cases map\n // moves the ports on the canvas and the ports the runtime activates.\n outputs: (config: any) => casePorts(config?.cases),\n configSchema: [\n { type: \"expression\", key: \"value\", label: \"Switch on\", example: \"{{ $json.kind }}\", required: true },\n {\n type: \"keyvalue\",\n key: \"cases\",\n label: \"Cases\",\n description: \"Match value → output port. Unmatched input takes `default`.\",\n keyLabel: \"When value is\",\n valueLabel: \"Route to port\",\n keyPlaceholder: \"a\",\n valuePlaceholder: \"case_a\",\n addLabel: \"Add case\",\n default: { a: \"case_a\", b: \"case_b\" },\n },\n ],\n },\n {\n name: \"@particle-academy/for_each\",\n aliases: [\"for_each\", \"@fancy/for_each\"],\n category: \"logic\",\n label: \"For Each\",\n description: \"Iterate over a list, emitting each item on `item`.\",\n icon: \"↻\",\n inputs: [{ id: \"in\" }],\n outputs: [{ id: \"item\", label: \"item\" }, { id: \"done\", label: \"done\" }],\n configSchema: [\n { type: \"expression\", key: \"source\", label: \"List\", example: \"{{ $json.users }}\", required: true },\n { type: \"number\", key: \"concurrency\", label: \"Concurrency\", default: 1, min: 1, max: 50 },\n ],\n },\n {\n name: \"@particle-academy/merge\",\n aliases: [\"merge\", \"@fancy/merge\"],\n category: \"logic\",\n label: \"Merge\",\n description: \"Combine multiple inputs into one object or array.\",\n icon: \"⊕\",\n inputs: [{ id: \"a\" }, { id: \"b\" }],\n outputs: [{ id: \"out\" }],\n configSchema: [\n { type: \"select\", key: \"mode\", label: \"Mode\", default: \"merge\",\n options: [{ value: \"merge\", label: \"Object merge\" }, { value: \"concat\", label: \"Array concat\" }] },\n ],\n },\n {\n name: \"@particle-academy/wait\",\n aliases: [\"wait\", \"@fancy/wait\"],\n category: \"logic\",\n label: \"Wait\",\n description: \"Sleep or wait for an external event.\",\n icon: \"⏸\",\n configSchema: [\n { type: \"select\", key: \"mode\", label: \"Mode\", default: \"duration\",\n options: [{ value: \"duration\", label: \"Duration\" }, { value: \"until\", label: \"Until timestamp\" }, { value: \"event\", label: \"External event\" }] },\n { type: \"text\", key: \"duration\", label: \"Duration\", placeholder: \"5s, 10m, 1h\", description: \"Used when mode = duration.\" },\n ],\n },\n {\n name: \"@particle-academy/transform\",\n aliases: [\"transform\", \"@fancy/transform\"],\n category: \"logic\",\n label: \"Transform\",\n description: \"Reshape data with an expression.\",\n icon: \"ƒ\",\n configSchema: [\n {\n type: \"select\", key: \"mode\", label: \"Build the output\", default: \"fields\",\n options: [\n { value: \"fields\", label: \"Field by field\" },\n { value: \"expression\", label: \"One expression\" },\n ],\n },\n {\n type: \"repeater\",\n key: \"fields\",\n label: \"Output fields\",\n description: \"Each row becomes a key on the result.\",\n titleKey: \"key\",\n addLabel: \"Add field\",\n fields: [\n { type: \"text\", key: \"key\", label: \"Key\", required: true, placeholder: \"name\" },\n { type: \"expression\", key: \"value\", label: \"Value\", example: \"{{ $json.first }}\", required: true },\n ],\n default: [{ key: \"\", value: \"\" }],\n },\n {\n type: \"expression\",\n key: \"expression\",\n label: \"Expression (advanced)\",\n example: \"{{ { id: $json.id, name: $json.first + ' ' + $json.last } }}\",\n description: \"Used when the mode above is set to one expression.\",\n },\n ],\n },\n\n // ───────────── Data ─────────────\n {\n name: \"@particle-academy/memory_store\",\n aliases: [\"memory_store\", \"@fancy/memory_store\"],\n category: \"data\",\n label: \"Memory Store\",\n description: \"Read or write per-conversation memory.\",\n icon: \"🧠\",\n configSchema: [\n { type: \"select\", key: \"operation\", label: \"Operation\", required: true, default: \"read\",\n options: [{ value: \"read\", label: \"Read\" }, { value: \"write\", label: \"Write\" }, { value: \"append\", label: \"Append\" }] },\n { type: \"text\", key: \"key\", label: \"Key\", placeholder: \"user.preferences\", required: true },\n { type: \"expression\", key: \"value\", label: \"Value (write/append only)\", example: \"{{ $json }}\" },\n { type: \"credential\", key: \"store\", label: \"Memory store\", credentialType: \"memory_store\" },\n ],\n },\n {\n name: \"@particle-academy/data_store\",\n aliases: [\"data_store\", \"@fancy/data_store\"],\n category: \"data\",\n label: \"Data Store\",\n description: \"Key-value or table read/write against a host store.\",\n icon: \"🗃\",\n configSchema: [\n { type: \"select\", key: \"operation\", label: \"Operation\", required: true, default: \"get\",\n options: [\n { value: \"get\", label: \"Get\" }, { value: \"set\", label: \"Set\" }, { value: \"delete\", label: \"Delete\" },\n { value: \"query\", label: \"Query\" }, { value: \"list\", label: \"List\" },\n ] },\n { type: \"text\", key: \"table\", label: \"Table / collection\", required: true },\n { type: \"text\", key: \"key\", label: \"Key\" },\n { type: \"keyvalue\", key: \"where\", label: \"Where\",\n description: \"Field/value pairs to match. For query and list operations.\",\n keyLabel: \"Field\", valueLabel: \"Equals\", addLabel: \"Add filter\" },\n { type: \"expression\", key: \"value\", label: \"Value (set only)\", example: \"{{ $json }}\" },\n { type: \"credential\", key: \"store\", label: \"Data store\", credentialType: \"data_store\" },\n ],\n },\n {\n name: \"@particle-academy/variable\",\n aliases: [\"variable\", \"@fancy/variable\"],\n category: \"data\",\n label: \"Variable\",\n description: \"Workflow-scoped value used by other nodes.\",\n icon: \"𝓍\",\n configSchema: [\n { type: \"text\", key: \"name\", label: \"Name\", required: true },\n { type: \"expression\", key: \"value\", label: \"Value\", required: true },\n ],\n },\n\n // ───────────── AI ─────────────\n {\n name: \"@particle-academy/llm_call\",\n aliases: [\"llm_call\", \"@fancy/llm_call\"],\n category: \"ai\",\n label: \"LLM Call\",\n description: \"Send a prompt + context to a model and receive a response.\",\n icon: \"✦\",\n configSchema: [\n { type: \"select\", key: \"provider\", label: \"Provider\", default: \"anthropic\",\n options: [\n { value: \"anthropic\", label: \"Anthropic\" },\n { value: \"openai\", label: \"OpenAI\" },\n { value: \"custom\", label: \"Custom\" },\n ] },\n { type: \"text\", key: \"model\", label: \"Model\", placeholder: \"claude-sonnet-4-5\", required: true },\n { type: \"textarea\", key: \"system\", label: \"System prompt\", rows: 4 },\n { type: \"expression\", key: \"prompt\", label: \"User prompt\", example: \"{{ $json.question }}\", required: true },\n { type: \"number\", key: \"temperature\", label: \"Temperature\", min: 0, max: 2, step: 0.1, default: 0.7 },\n { type: \"number\", key: \"max_tokens\", label: \"Max tokens\", min: 1, max: 8192, default: 1024 },\n {\n type: \"repeater\", key: \"tools\", label: \"Tools\",\n description: \"Tools the model may call.\",\n titleKey: \"name\", addLabel: \"Add tool\",\n fields: [\n { type: \"text\", key: \"name\", label: \"Name\", required: true, placeholder: \"search_index\" },\n { type: \"text\", key: \"description\", label: \"When to use it\" },\n { type: \"json\", key: \"input_schema\", label: \"Input schema\",\n description: \"JSON Schema for the tool's arguments.\" },\n ],\n },\n { type: \"credential\", key: \"credential\", label: \"API credential\", credentialType: \"llm_credential\" },\n ],\n },\n {\n name: \"@particle-academy/llm_router\",\n // Every id this node has ever shipped under keeps resolving — MOIC's saved\n // flows carry the bare `llm_branch`.\n aliases: [\"llm_router\", \"llm_branch\", \"@fancy/llm_branch\", \"@fancy/llm_router\"],\n category: \"ai\",\n label: \"LLM Router\",\n description: \"Let a model choose which route the flow takes.\",\n icon: \"✧\",\n inputs: [{ id: \"in\" }],\n // Each declared route is a port. The executor returns `{ __port: id }`\n // (or `Port.only(id)` on the PHP runtime) to pick one.\n outputs: (config: any) => routePorts(config?.routes, config?.fallback),\n // A shuttle, not an engine: it carries the routes out to whatever LLM\n // client the host registered and carries the choice back. No provider SDK\n // reaches core, so this stays a builtin without adding a dependency.\n executor: llmRouterExecutor,\n configSchema: [\n { type: \"textarea\", key: \"system\", label: \"System prompt\", rows: 3,\n description: \"Optional framing for the routing decision.\" },\n { type: \"expression\", key: \"prompt\", label: \"What to route on\",\n example: \"{{ $json.message }}\", required: true },\n {\n type: \"repeater\",\n key: \"routes\",\n label: \"Routes\",\n description: \"The model picks exactly one. Descriptions are what it chooses between — make them distinct.\",\n titleKey: \"port\",\n addLabel: \"Add route\",\n minItems: 2,\n fields: [\n { type: \"text\", key: \"port\", label: \"Port\", required: true, placeholder: \"billing\" },\n { type: \"text\", key: \"description\", label: \"When to choose it\", required: true,\n placeholder: \"The user is asking about an invoice, refund, or payment.\" },\n ],\n default: [\n { port: \"a\", description: \"Describe when the model should pick this route.\" },\n { port: \"b\", description: \"Describe when the model should pick this route.\" },\n ],\n },\n { type: \"select\", key: \"provider\", label: \"Provider\", default: \"anthropic\",\n options: [\n { value: \"anthropic\", label: \"Anthropic\" },\n { value: \"openai\", label: \"OpenAI\" },\n { value: \"custom\", label: \"Custom\" },\n ] },\n { type: \"text\", key: \"model\", label: \"Model\", placeholder: \"claude-sonnet-4-5\" },\n { type: \"switch\", key: \"fallback\", label: \"Add a `fallback` port\", default: true,\n description: \"Where the flow goes if the model returns no usable route.\" },\n { type: \"credential\", key: \"credential\", label: \"API credential\", credentialType: \"llm_credential\" },\n ],\n },\n {\n name: \"@particle-academy/tool_use\",\n aliases: [\"tool_use\", \"@fancy/tool_use\"],\n category: \"ai\",\n label: \"Tool Use\",\n description: \"Hand control to a host-registered tool by name.\",\n icon: \"🛠\",\n configSchema: [\n { type: \"text\", key: \"tool\", label: \"Tool name\", placeholder: \"search_index\", required: true },\n { type: \"expression\", key: \"args\", label: \"Arguments\", example: \"{{ { query: $json.q } }}\" },\n ],\n },\n {\n name: \"@particle-academy/embed_search\",\n aliases: [\"embed_search\", \"@fancy/embed_search\"],\n category: \"ai\",\n label: \"Embed & Search\",\n description: \"Embed a query and search a vector store.\",\n icon: \"✺\",\n configSchema: [\n { type: \"expression\", key: \"query\", label: \"Query\", required: true, example: \"{{ $json.question }}\" },\n { type: \"number\", key: \"topK\", label: \"Top K\", default: 5, min: 1, max: 50 },\n { type: \"credential\", key: \"vectorStore\", label: \"Vector store\", credentialType: \"vector_store\" },\n ],\n },\n\n // ───────────── IO ─────────────\n {\n name: \"@particle-academy/api_request\",\n aliases: [\"api_request\", \"@fancy/api_request\"],\n category: \"io\",\n label: \"API Request\",\n description: \"HTTP request to any URL.\",\n icon: \"↔\",\n configSchema: [\n ...HTTP_METHODS,\n { type: \"text\", key: \"url\", label: \"URL\", placeholder: \"https://api.example.com/...\", required: true },\n { type: \"keyvalue\", key: \"headers\", label: \"Headers\",\n keyLabel: \"Header\", valueLabel: \"Value\",\n keyPlaceholder: \"content-type\", valuePlaceholder: \"application/json\",\n addLabel: \"Add header\",\n default: { \"content-type\": \"application/json\" } },\n { type: \"json\", key: \"body\", label: \"Body\" },\n { type: \"credential\", key: \"auth\", label: \"Auth\", credentialType: \"api_credential\" },\n ],\n },\n {\n name: \"@particle-academy/webhook_out\",\n aliases: [\"webhook_out\", \"@fancy/webhook_out\"],\n category: \"io\",\n label: \"Send Webhook\",\n description: \"POST a payload to a configured URL.\",\n icon: \"↗\",\n configSchema: [\n { type: \"text\", key: \"url\", label: \"URL\", required: true },\n { type: \"keyvalue\", key: \"headers\", label: \"Headers\",\n keyLabel: \"Header\", valueLabel: \"Value\", addLabel: \"Add header\" },\n { type: \"expression\", key: \"payload\", label: \"Payload\", required: true, example: \"{{ $json }}\" },\n ],\n },\n\n // ───────────── Human ─────────────\n {\n name: \"@particle-academy/human_approval\",\n aliases: [\"human_approval\", \"@fancy/human_approval\"],\n pausesForHuman: \"approval\",\n category: \"human\",\n label: \"Human Approval\",\n description: \"Pause until a human approves or denies.\",\n icon: \"✓\",\n inputs: [{ id: \"in\" }],\n outputs: [{ id: \"approved\", label: \"approved\" }, { id: \"denied\", label: \"denied\" }],\n configSchema: [\n { type: \"text\", key: \"title\", label: \"Approval title\", default: \"Approve action\" },\n { type: \"textarea\", key: \"description\", label: \"Description for approver\", rows: 3 },\n { type: \"credential\", key: \"channel\", label: \"Notify channel\", credentialType: \"notify_channel\" },\n ],\n },\n {\n name: \"@particle-academy/notify\",\n aliases: [\"notify\", \"@fancy/notify\"],\n category: \"human\",\n label: \"Notify\",\n description: \"Send a message via Slack / email / SMS / etc.\",\n icon: \"🔔\",\n configSchema: [\n { type: \"select\", key: \"channel\", label: \"Channel\", default: \"slack\",\n options: [\n { value: \"slack\", label: \"Slack\" }, { value: \"email\", label: \"Email\" },\n { value: \"sms\", label: \"SMS\" }, { value: \"discord\", label: \"Discord\" },\n ] },\n { type: \"text\", key: \"to\", label: \"To\", required: true },\n { type: \"expression\", key: \"message\", label: \"Message\", required: true, example: \"{{ $json.summary }}\" },\n ],\n },\n\n // ───────────── Output ─────────────\n {\n name: \"@particle-academy/output\",\n aliases: [\"output\", \"@fancy/output\"],\n category: \"output\",\n label: \"Output\",\n description: \"Terminal node — captures the workflow's result.\",\n icon: \"●\",\n inputs: [{ id: \"in\" }],\n outputs: [],\n },\n {\n name: \"@particle-academy/log\",\n aliases: [\"log\", \"@fancy/log\"],\n category: \"output\",\n label: \"Log\",\n description: \"Send to the run feed.\",\n icon: \"≡\",\n inputs: [{ id: \"in\" }],\n outputs: [],\n configSchema: [\n { type: \"select\", key: \"level\", label: \"Level\", default: \"info\",\n options: [{ value: \"info\", label: \"info\" }, { value: \"warn\", label: \"warn\" }, { value: \"error\", label: \"error\" }] },\n { type: \"expression\", key: \"message\", label: \"Message\", required: true, example: \"{{ $json }}\" },\n ],\n },\n {\n // Swimlane — a portless, resizable container. Child nodes are parented into\n // it; it never runs (the runtime skips the `layout` category). Uses its own\n // renderer (LaneNode) instead of the default card.\n name: \"@particle-academy/lane\",\n aliases: [\"lane\", \"@fancy/lane\"],\n category: \"layout\",\n label: \"Lane\",\n description: \"A resizable swimlane — drop nodes into it to group them.\",\n icon: \"▤\",\n inputs: [],\n outputs: [],\n configSchema: [\n { type: \"text\", key: \"title\", label: \"Title\", default: \"Lane\" },\n { type: \"select\", key: \"orientation\", label: \"Orientation\", default: \"horizontal\",\n options: [{ value: \"horizontal\", label: \"Row\" }, { value: \"vertical\", label: \"Column\" }] },\n ],\n defaultConfig: { title: \"Lane\", orientation: \"horizontal\" },\n resizable: { minWidth: 160, minHeight: 72 },\n component: LaneNode,\n },\n];\n\n/** Register every built-in kind. Idempotent via the registry. */\nexport function registerBuiltinKinds(): void {\n for (const k of KINDS) registerNodeKind(k);\n}\n\n/** Exported list for hosts that want to selectively re-register. */\nexport const BUILTIN_KINDS: NodeKindDefinition[] = KINDS;\n","export type {\n ConfigField,\n TextConfigField,\n TextareaConfigField,\n NumberConfigField,\n SelectConfigField,\n SwitchConfigField,\n JsonConfigField,\n ExpressionConfigField,\n CredentialConfigField,\n RepeaterConfigField,\n RepeaterRowField,\n KeyValueConfigField,\n DocumentConfigField,\n NodeCategory,\n NodeKindDefinition,\n PortSpec,\n RenderBodyContext,\n} from \"./types\";\n\nexport { resolvePortSpec, resolveNodePorts, nodeConfig } from \"./ports\";\n\nexport {\n createConnectionValidator,\n defaultPortCompatibility,\n ANY_PORT_TYPE,\n type PortCompatibility,\n type ConnectionValidatorOptions,\n} from \"./connection\";\n\n/** Host capabilities — core declares the contract, the host supplies the impl. */\nexport {\n registerLlmClient,\n getLlmClient,\n registerWorkflowResolver,\n getWorkflowResolver,\n capabilityStatus,\n type LlmClient,\n type LlmRoute,\n type LlmRouteRequest,\n type LlmRouteChoice,\n type WorkflowResolver,\n type WorkflowResolution,\n type WorkflowResolutionFailure,\n type CapabilityId,\n isResolutionFailure,\n} from \"./capabilities\";\n\n/**\n * The human-pause contract — a run waiting for a person, not a failure.\n * `decodePause` is the one function a durable runner needs.\n */\nexport {\n pauseForHuman,\n encodePause,\n decodePause,\n isPause,\n PAUSE_PREFIX,\n LEGACY_PAUSE_PREFIXES,\n type PauseAwaiting,\n type PauseSignal,\n} from \"./pause\";\n\nexport { subflowExecutor, subflowPorts, subflowMode, DEFAULT_MAX_DEPTH, type SubflowMode } from \"./subflow\";\nexport { llmRouterExecutor, declaredRoutes, resolveFallbackPort } from \"./llm-router\";\n/** @deprecated Renamed to `llmRouterExecutor` — the id and label now match. */\nexport { llmRouterExecutor as llmBranchExecutor } from \"./llm-router\";\n\nexport {\n registerRichInputAdapter,\n getRichInputAdapter,\n isRichInputEnabled,\n onRichInputAdapterChanged,\n RichInputPreview,\n type RichInputAdapter,\n} from \"./rich-input\";\n\nexport {\n registerNodeKind,\n getNodeKind,\n resolveKindId,\n kindIds,\n listNodeKinds,\n onNodeKindsChanged,\n defaultConfigFor,\n validateConfig,\n categoryAccent,\n} from \"./registry\";\n\nexport { RegistryNode } from \"./RegistryNode\";\nexport { registerBuiltinKinds, BUILTIN_KINDS } from \"./builtin\";\n\nimport type { NodeTypes } from \"@xyflow/react\";\nimport { RegistryNode } from \"./RegistryNode\";\nimport { kindIds, listNodeKinds } from \"./registry\";\n\n/**\n * Build an xyflow `nodeTypes` map from the registry — every registered\n * kind gets `RegistryNode` as its renderer. Refresh manually via\n * `useNodeTypes()` (a hook that subscribes to registry changes).\n */\nexport function buildNodeTypes(): NodeTypes {\n const map: NodeTypes = {};\n for (const k of listNodeKinds()) {\n // A kind may bring its own full renderer (lanes/containers); otherwise the\n // default card. Key on every id the kind answers to, not just the canonical\n // one — xyflow looks the renderer up by `node.type` BEFORE RegistryNode gets\n // a chance to resolve aliases, so a graph carrying a pre-namespace type would\n // otherwise fall through to the unknown-node placeholder.\n const renderer = k.component ?? RegistryNode;\n for (const id of kindIds(k)) map[id] = renderer;\n }\n return map;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/registry/registry.ts"],"names":[],"mappings":"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","file":"chunk-YXRLIV7A.js","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"]}