@particle-academy/fancy-flow 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { useFlowState, useFlowRun, applyStatusesToNodes } from './chunk-MFMRTRPO.js';
2
2
  export { applyStatusesToNodes, useFlowRun, useFlowState } from './chunk-MFMRTRPO.js';
3
- import { buildNodeTypes, registerBuiltinKinds } from './chunk-WEZJFMLV.js';
4
- export { BUILTIN_KINDS, RegistryNode, buildNodeTypes, registerBuiltinKinds } from './chunk-WEZJFMLV.js';
3
+ import { buildNodeTypes, registerBuiltinKinds } from './chunk-7U3EP4Q5.js';
4
+ export { BUILTIN_KINDS, RegistryNode, buildNodeTypes, registerBuiltinKinds } from './chunk-7U3EP4Q5.js';
5
5
  import { ReactFlowProvider, useReactFlow, addEdge, applyEdgeChanges, applyNodeChanges, Position, Handle, index, BackgroundVariant, Background, Controls, MiniMap } from './chunk-NF6NPY5N.js';
6
6
  export { runFlow } from './chunk-L4AX73Q6.js';
7
7
  import { workflowToBlob, importWorkflow, exportWorkflow } from './chunk-D6W5FMCT.js';
@@ -98,7 +98,7 @@ declare function declaredRoutes(config: Record<string, unknown>): LlmRoute[];
98
98
  * route, and always loudly.
99
99
  */
100
100
  declare function resolveFallbackPort(routes: LlmRoute[], fallbackEnabled: boolean): string;
101
- declare const llmBranchExecutor: NodeExecutor;
101
+ declare const llmRouterExecutor: NodeExecutor;
102
102
 
103
103
  /**
104
104
  * Rich user input — the injection point.
@@ -230,4 +230,4 @@ declare const BUILTIN_KINDS: NodeKindDefinition[];
230
230
  */
231
231
  declare function buildNodeTypes(): NodeTypes;
232
232
 
233
- export { BUILTIN_KINDS, DEFAULT_MAX_DEPTH, LlmRoute, NodeKindDefinition, PortSpec, RegistryNode, type RichInputAdapter, RichInputPreview, type SubflowMode, buildNodeTypes, categoryAccent, declaredRoutes, defaultConfigFor, getNodeKind, getRichInputAdapter, isRichInputEnabled, kindIds, listNodeKinds, llmBranchExecutor, nodeConfig, onNodeKindsChanged, onRichInputAdapterChanged, registerBuiltinKinds, registerNodeKind, registerRichInputAdapter, resolveFallbackPort, resolveKindId, resolveNodePorts, resolvePortSpec, subflowExecutor, subflowMode, subflowPorts, validateConfig };
233
+ export { BUILTIN_KINDS, DEFAULT_MAX_DEPTH, LlmRoute, NodeKindDefinition, PortSpec, RegistryNode, type RichInputAdapter, RichInputPreview, type SubflowMode, buildNodeTypes, categoryAccent, declaredRoutes, defaultConfigFor, getNodeKind, getRichInputAdapter, isRichInputEnabled, kindIds, listNodeKinds, llmRouterExecutor as llmBranchExecutor, llmRouterExecutor, nodeConfig, onNodeKindsChanged, onRichInputAdapterChanged, registerBuiltinKinds, registerNodeKind, registerRichInputAdapter, resolveFallbackPort, resolveKindId, resolveNodePorts, resolvePortSpec, subflowExecutor, subflowMode, subflowPorts, validateConfig };
@@ -98,7 +98,7 @@ declare function declaredRoutes(config: Record<string, unknown>): LlmRoute[];
98
98
  * route, and always loudly.
99
99
  */
100
100
  declare function resolveFallbackPort(routes: LlmRoute[], fallbackEnabled: boolean): string;
101
- declare const llmBranchExecutor: NodeExecutor;
101
+ declare const llmRouterExecutor: NodeExecutor;
102
102
 
103
103
  /**
104
104
  * Rich user input — the injection point.
@@ -230,4 +230,4 @@ declare const BUILTIN_KINDS: NodeKindDefinition[];
230
230
  */
231
231
  declare function buildNodeTypes(): NodeTypes;
232
232
 
233
- export { BUILTIN_KINDS, DEFAULT_MAX_DEPTH, LlmRoute, NodeKindDefinition, PortSpec, RegistryNode, type RichInputAdapter, RichInputPreview, type SubflowMode, buildNodeTypes, categoryAccent, declaredRoutes, defaultConfigFor, getNodeKind, getRichInputAdapter, isRichInputEnabled, kindIds, listNodeKinds, llmBranchExecutor, nodeConfig, onNodeKindsChanged, onRichInputAdapterChanged, registerBuiltinKinds, registerNodeKind, registerRichInputAdapter, resolveFallbackPort, resolveKindId, resolveNodePorts, resolvePortSpec, subflowExecutor, subflowMode, subflowPorts, validateConfig };
233
+ export { BUILTIN_KINDS, DEFAULT_MAX_DEPTH, LlmRoute, NodeKindDefinition, PortSpec, RegistryNode, type RichInputAdapter, RichInputPreview, type SubflowMode, buildNodeTypes, categoryAccent, declaredRoutes, defaultConfigFor, getNodeKind, getRichInputAdapter, isRichInputEnabled, kindIds, listNodeKinds, llmRouterExecutor as llmBranchExecutor, llmRouterExecutor, nodeConfig, onNodeKindsChanged, onRichInputAdapterChanged, registerBuiltinKinds, registerNodeKind, registerRichInputAdapter, resolveFallbackPort, resolveKindId, resolveNodePorts, resolvePortSpec, subflowExecutor, subflowMode, subflowPorts, validateConfig };
package/dist/registry.cjs CHANGED
@@ -431,7 +431,7 @@ var subflowExecutor = async (ctx) => {
431
431
  return { __port: "out", value: result.outputs };
432
432
  };
433
433
 
434
- // src/registry/llm-branch.ts
434
+ // src/registry/llm-router.ts
435
435
  function declaredRoutes(config) {
436
436
  const raw = config.routes;
437
437
  if (!Array.isArray(raw)) return [];
@@ -441,11 +441,11 @@ function resolveFallbackPort(routes, fallbackEnabled) {
441
441
  if (fallbackEnabled) return "fallback";
442
442
  return routes[0]?.port ?? "out";
443
443
  }
444
- var llmBranchExecutor = async (ctx) => {
444
+ var llmRouterExecutor = async (ctx) => {
445
445
  const config = ctx.node.data?.config ?? {};
446
446
  const routes = declaredRoutes(config);
447
447
  if (routes.length === 0) {
448
- ctx.abort("llm_branch has no routes configured");
448
+ ctx.abort("llm_router has no routes configured");
449
449
  }
450
450
  const client = getLlmClient();
451
451
  if (!client) {
@@ -471,7 +471,7 @@ var llmBranchExecutor = async (ctx) => {
471
471
  type: "log",
472
472
  nodeId: ctx.node.id,
473
473
  level: "warn",
474
- message: `llm_branch: model returned "${port || "(nothing)"}", which is not a declared route. Routing to "${safe}".`
474
+ message: `llm_router: model returned "${port || "(nothing)"}", which is not a declared route. Routing to "${safe}".`
475
475
  });
476
476
  reason = reason ?? `unrecognised route "${port}"`;
477
477
  port = safe;
@@ -9734,10 +9734,13 @@ var KINDS = [
9734
9734
  description: "Streaming adds a second port so a parent can show progress instead of a spinner."
9735
9735
  },
9736
9736
  {
9737
- type: "json",
9737
+ type: "keyvalue",
9738
9738
  key: "inputs",
9739
9739
  label: "Input mapping",
9740
- description: "Entry-point inputs for the child run. Omit to pass this node's inputs straight through."
9740
+ description: "Values handed to the child's entry points. Omit to pass this node's inputs straight through.",
9741
+ keyLabel: "Name",
9742
+ valueLabel: "Value",
9743
+ addLabel: "Add input"
9741
9744
  },
9742
9745
  {
9743
9746
  type: "number",
@@ -9761,7 +9764,57 @@ var KINDS = [
9761
9764
  inputs: [{ id: "in" }],
9762
9765
  outputs: [{ id: "true", label: "true" }, { id: "false", label: "false" }],
9763
9766
  configSchema: [
9764
- { type: "expression", key: "condition", label: "Condition", example: "{{ $json.active }}", required: true }
9767
+ {
9768
+ type: "select",
9769
+ key: "match",
9770
+ label: "Match",
9771
+ default: "all",
9772
+ options: [
9773
+ { value: "all", label: "All conditions (AND)" },
9774
+ { value: "any", label: "Any condition (OR)" }
9775
+ ]
9776
+ },
9777
+ {
9778
+ type: "repeater",
9779
+ key: "conditions",
9780
+ label: "Conditions",
9781
+ description: "Routes to `true` when these match, otherwise `false`.",
9782
+ titleKey: "left",
9783
+ addLabel: "Add condition",
9784
+ minItems: 1,
9785
+ fields: [
9786
+ { type: "expression", key: "left", label: "Value", example: "{{ $json.status }}", required: true },
9787
+ {
9788
+ type: "select",
9789
+ key: "operator",
9790
+ label: "Is",
9791
+ default: "eq",
9792
+ options: [
9793
+ { value: "eq", label: "equal to" },
9794
+ { value: "neq", label: "not equal to" },
9795
+ { value: "contains", label: "contains" },
9796
+ { value: "not_contains", label: "does not contain" },
9797
+ { value: "gt", label: "greater than" },
9798
+ { value: "gte", label: "greater than or equal to" },
9799
+ { value: "lt", label: "less than" },
9800
+ { value: "lte", label: "less than or equal to" },
9801
+ { value: "truthy", label: "true" },
9802
+ { value: "falsy", label: "false" },
9803
+ { value: "empty", label: "empty" },
9804
+ { value: "not_empty", label: "not empty" }
9805
+ ]
9806
+ },
9807
+ { type: "text", key: "right", label: "Compared to", placeholder: "active" }
9808
+ ],
9809
+ default: [{ left: "", operator: "eq", right: "" }]
9810
+ },
9811
+ {
9812
+ type: "expression",
9813
+ key: "condition",
9814
+ label: "Raw expression (advanced)",
9815
+ example: "{{ $json.active && $json.score > 10 }}",
9816
+ description: "Escape hatch for logic the builder can't express. Overrides the conditions above when set."
9817
+ }
9765
9818
  ]
9766
9819
  },
9767
9820
  {
@@ -9851,12 +9904,35 @@ var KINDS = [
9851
9904
  description: "Reshape data with an expression.",
9852
9905
  icon: "\u0192",
9853
9906
  configSchema: [
9907
+ {
9908
+ type: "select",
9909
+ key: "mode",
9910
+ label: "Build the output",
9911
+ default: "fields",
9912
+ options: [
9913
+ { value: "fields", label: "Field by field" },
9914
+ { value: "expression", label: "One expression" }
9915
+ ]
9916
+ },
9917
+ {
9918
+ type: "repeater",
9919
+ key: "fields",
9920
+ label: "Output fields",
9921
+ description: "Each row becomes a key on the result.",
9922
+ titleKey: "key",
9923
+ addLabel: "Add field",
9924
+ fields: [
9925
+ { type: "text", key: "key", label: "Key", required: true, placeholder: "name" },
9926
+ { type: "expression", key: "value", label: "Value", example: "{{ $json.first }}", required: true }
9927
+ ],
9928
+ default: [{ key: "", value: "" }]
9929
+ },
9854
9930
  {
9855
9931
  type: "expression",
9856
9932
  key: "expression",
9857
- label: "Expression",
9933
+ label: "Expression (advanced)",
9858
9934
  example: "{{ { id: $json.id, name: $json.first + ' ' + $json.last } }}",
9859
- required: true
9935
+ description: "Used when the mode above is set to one expression."
9860
9936
  }
9861
9937
  ]
9862
9938
  },
@@ -9906,7 +9982,15 @@ var KINDS = [
9906
9982
  },
9907
9983
  { type: "text", key: "table", label: "Table / collection", required: true },
9908
9984
  { type: "text", key: "key", label: "Key" },
9909
- { type: "json", key: "where", label: "Where (JSON)", description: "For query/list operations." },
9985
+ {
9986
+ type: "keyvalue",
9987
+ key: "where",
9988
+ label: "Where",
9989
+ description: "Field/value pairs to match. For query and list operations.",
9990
+ keyLabel: "Field",
9991
+ valueLabel: "Equals",
9992
+ addLabel: "Add filter"
9993
+ },
9910
9994
  { type: "expression", key: "value", label: "Value (set only)", example: "{{ $json }}" },
9911
9995
  { type: "credential", key: "store", label: "Data store", credentialType: "data_store" }
9912
9996
  ]
@@ -9948,13 +10032,32 @@ var KINDS = [
9948
10032
  { type: "expression", key: "prompt", label: "User prompt", example: "{{ $json.question }}", required: true },
9949
10033
  { type: "number", key: "temperature", label: "Temperature", min: 0, max: 2, step: 0.1, default: 0.7 },
9950
10034
  { type: "number", key: "max_tokens", label: "Max tokens", min: 1, max: 8192, default: 1024 },
9951
- { type: "json", key: "tools", label: "Tools (JSON)", description: "Optional Anthropic-style tool definitions." },
10035
+ {
10036
+ type: "repeater",
10037
+ key: "tools",
10038
+ label: "Tools",
10039
+ description: "Tools the model may call.",
10040
+ titleKey: "name",
10041
+ addLabel: "Add tool",
10042
+ fields: [
10043
+ { type: "text", key: "name", label: "Name", required: true, placeholder: "search_index" },
10044
+ { type: "text", key: "description", label: "When to use it" },
10045
+ {
10046
+ type: "json",
10047
+ key: "input_schema",
10048
+ label: "Input schema",
10049
+ description: "JSON Schema for the tool's arguments."
10050
+ }
10051
+ ]
10052
+ },
9952
10053
  { type: "credential", key: "credential", label: "API credential", credentialType: "llm_credential" }
9953
10054
  ]
9954
10055
  },
9955
10056
  {
9956
- name: "@particle-academy/llm_branch",
9957
- aliases: ["llm_branch", "@fancy/llm_branch"],
10057
+ name: "@particle-academy/llm_router",
10058
+ // Every id this node has ever shipped under keeps resolving — MOIC's saved
10059
+ // flows carry the bare `llm_branch`.
10060
+ aliases: ["llm_router", "llm_branch", "@fancy/llm_branch", "@fancy/llm_router"],
9958
10061
  category: "ai",
9959
10062
  label: "LLM Router",
9960
10063
  description: "Let a model choose which route the flow takes.",
@@ -9966,7 +10069,7 @@ var KINDS = [
9966
10069
  // A shuttle, not an engine: it carries the routes out to whatever LLM
9967
10070
  // client the host registered and carries the choice back. No provider SDK
9968
10071
  // reaches core, so this stays a builtin without adding a dependency.
9969
- executor: llmBranchExecutor,
10072
+ executor: llmRouterExecutor,
9970
10073
  configSchema: [
9971
10074
  {
9972
10075
  type: "textarea",
@@ -10063,7 +10166,17 @@ var KINDS = [
10063
10166
  configSchema: [
10064
10167
  ...HTTP_METHODS,
10065
10168
  { type: "text", key: "url", label: "URL", placeholder: "https://api.example.com/...", required: true },
10066
- { type: "json", key: "headers", label: "Headers", default: { "content-type": "application/json" } },
10169
+ {
10170
+ type: "keyvalue",
10171
+ key: "headers",
10172
+ label: "Headers",
10173
+ keyLabel: "Header",
10174
+ valueLabel: "Value",
10175
+ keyPlaceholder: "content-type",
10176
+ valuePlaceholder: "application/json",
10177
+ addLabel: "Add header",
10178
+ default: { "content-type": "application/json" }
10179
+ },
10067
10180
  { type: "json", key: "body", label: "Body" },
10068
10181
  { type: "credential", key: "auth", label: "Auth", credentialType: "api_credential" }
10069
10182
  ]
@@ -10077,7 +10190,14 @@ var KINDS = [
10077
10190
  icon: "\u2197",
10078
10191
  configSchema: [
10079
10192
  { type: "text", key: "url", label: "URL", required: true },
10080
- { type: "json", key: "headers", label: "Headers" },
10193
+ {
10194
+ type: "keyvalue",
10195
+ key: "headers",
10196
+ label: "Headers",
10197
+ keyLabel: "Header",
10198
+ valueLabel: "Value",
10199
+ addLabel: "Add header"
10200
+ },
10081
10201
  { type: "expression", key: "payload", label: "Payload", required: true, example: "{{ $json }}" }
10082
10202
  ]
10083
10203
  },
@@ -10183,7 +10303,8 @@ exports.getWorkflowResolver = getWorkflowResolver;
10183
10303
  exports.isRichInputEnabled = isRichInputEnabled;
10184
10304
  exports.kindIds = kindIds;
10185
10305
  exports.listNodeKinds = listNodeKinds;
10186
- exports.llmBranchExecutor = llmBranchExecutor;
10306
+ exports.llmBranchExecutor = llmRouterExecutor;
10307
+ exports.llmRouterExecutor = llmRouterExecutor;
10187
10308
  exports.nodeConfig = nodeConfig;
10188
10309
  exports.onNodeKindsChanged = onNodeKindsChanged;
10189
10310
  exports.onRichInputAdapterChanged = onRichInputAdapterChanged;