@particle-academy/fancy-flow 0.13.0 → 0.15.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/README.md +48 -0
- package/dist/{capabilities-D-V9Rxv1.d.cts → capabilities-BEbLqnJU.d.cts} +1 -1
- package/dist/{capabilities-B6r1Snfj.d.ts → capabilities-CI3gw0C7.d.ts} +1 -1
- package/dist/chunk-UEOE6B52.js +39 -0
- package/dist/chunk-UEOE6B52.js.map +1 -0
- package/dist/{chunk-WEZJFMLV.js → chunk-ZQBWPYTI.js} +142 -19
- package/dist/chunk-ZQBWPYTI.js.map +1 -0
- package/dist/engine.cjs +299 -0
- package/dist/engine.cjs.map +1 -1
- package/dist/engine.d.cts +190 -27
- package/dist/engine.d.ts +190 -27
- package/dist/engine.js +258 -2
- package/dist/engine.js.map +1 -1
- package/dist/index.cjs +181 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -6
- package/dist/index.d.ts +7 -6
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/llm/vercel-ai.d.cts +2 -2
- package/dist/llm/vercel-ai.d.ts +2 -2
- package/dist/pause-9iT4tCEV.d.cts +96 -0
- package/dist/pause-9iT4tCEV.d.ts +96 -0
- package/dist/registry/index.d.cts +8 -7
- package/dist/registry/index.d.ts +8 -7
- package/dist/registry.cjs +183 -17
- package/dist/registry.cjs.map +1 -1
- package/dist/registry.js +2 -1
- package/dist/run-flow-ChBi6q-W.d.ts +35 -0
- package/dist/run-flow-VKm57Hcj.d.cts +35 -0
- package/dist/runtime/index.d.cts +3 -3
- package/dist/runtime/index.d.ts +3 -3
- package/dist/schema/index.d.cts +1 -1
- package/dist/schema/index.d.ts +1 -1
- package/dist/{types-H60tQAxr.d.cts → types-D_jOR3Z2.d.cts} +12 -1
- package/dist/{types-CnnKPnpt.d.ts → types-NerkPtHS.d.ts} +12 -1
- package/dist/{types-fc0fFKkf.d.cts → types-sOmpCitB.d.cts} +1 -1
- package/dist/{types-fc0fFKkf.d.ts → types-sOmpCitB.d.ts} +1 -1
- package/dist/ux.d.cts +3 -2
- package/dist/ux.d.ts +3 -2
- package/package.json +1 -1
- package/dist/chunk-WEZJFMLV.js.map +0 -1
package/dist/llm/vercel-ai.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { LanguageModel } from 'ai';
|
|
2
|
-
import { L as LlmRouteRequest, a as LlmClient } from '../capabilities-
|
|
3
|
-
import '../types-
|
|
2
|
+
import { L as LlmRouteRequest, a as LlmClient } from '../capabilities-BEbLqnJU.cjs';
|
|
3
|
+
import '../types-sOmpCitB.cjs';
|
|
4
4
|
import '@xyflow/react';
|
|
5
5
|
|
|
6
6
|
/**
|
package/dist/llm/vercel-ai.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { LanguageModel } from 'ai';
|
|
2
|
-
import { L as LlmRouteRequest, a as LlmClient } from '../capabilities-
|
|
3
|
-
import '../types-
|
|
2
|
+
import { L as LlmRouteRequest, a as LlmClient } from '../capabilities-CI3gw0C7.js';
|
|
3
|
+
import '../types-sOmpCitB.js';
|
|
4
4
|
import '@xyflow/react';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The human-pause contract.
|
|
3
|
+
*
|
|
4
|
+
* A workflow that waits for a person is not an error, but it travels the same
|
|
5
|
+
* channel as one: the executor aborts, the engine records a reason string, and
|
|
6
|
+
* the durable runner decides whether that string meant "failed" or "waiting".
|
|
7
|
+
*
|
|
8
|
+
* That seam existed before this module, as two `str_starts_with` checks in the
|
|
9
|
+
* Laravel run job against constants owned by two BUILTIN executors. It worked,
|
|
10
|
+
* and it was invisible: a third-party human-input node had no way to announce
|
|
11
|
+
* that it pauses, and nothing stopped a refactor from removing the mechanism
|
|
12
|
+
* out from under published packages. Reported by the MOIC Suite consumer, who
|
|
13
|
+
* needed exactly that and had to reach for a private constant to get it.
|
|
14
|
+
*
|
|
15
|
+
* So the encoding is now public, typed, and versioned by prefix rather than
|
|
16
|
+
* implied. The wire format stays a plain string on purpose — it survives the
|
|
17
|
+
* existing abort → `RunResult.error` path unchanged, crosses a queue boundary,
|
|
18
|
+
* and decodes identically in PHP, none of which a thrown class would do.
|
|
19
|
+
*
|
|
20
|
+
* @see decodePause — the one function a durable runner needs.
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* What the run is waiting for.
|
|
24
|
+
*
|
|
25
|
+
* `approval` and `input` are the shapes both runtimes ship. The type stays open
|
|
26
|
+
* because the whole point is that a marketplace node can define its own —
|
|
27
|
+
* a signature step, a payment confirmation, a review queue — and a runner that
|
|
28
|
+
* does not recognise one should report it rather than guess.
|
|
29
|
+
*/
|
|
30
|
+
type PauseAwaiting = "approval" | "input" | (string & {});
|
|
31
|
+
/** A run halted, waiting for a person. */
|
|
32
|
+
type PauseSignal = {
|
|
33
|
+
/** The node that paused — where a submission gets injected on resume. */
|
|
34
|
+
nodeId: string;
|
|
35
|
+
awaiting: PauseAwaiting;
|
|
36
|
+
/**
|
|
37
|
+
* Kind-supplied context for whoever renders the wait — a form schema, the
|
|
38
|
+
* question being asked, a diff to approve. Must be JSON-serializable: it
|
|
39
|
+
* crosses a queue boundary and, for durable runs, a database column.
|
|
40
|
+
*/
|
|
41
|
+
detail?: unknown;
|
|
42
|
+
};
|
|
43
|
+
/** Marks a reason string as a pause rather than a failure. */
|
|
44
|
+
declare const PAUSE_PREFIX = "fancy-flow:pause:";
|
|
45
|
+
/**
|
|
46
|
+
* Reason prefixes shipped before this contract, kept decodable forever.
|
|
47
|
+
*
|
|
48
|
+
* These are what `DurableApprovalExecutor` and `DurableUserInputExecutor`
|
|
49
|
+
* emitted, and they are written into the `error` column of every run that
|
|
50
|
+
* paused under an older version. Dropping them would strand those runs
|
|
51
|
+
* mid-flight — a resume path that only works for new runs is not a resume path.
|
|
52
|
+
*/
|
|
53
|
+
declare const LEGACY_PAUSE_PREFIXES: ReadonlyArray<readonly [string, PauseAwaiting]>;
|
|
54
|
+
/**
|
|
55
|
+
* Encode a pause as the reason string an executor aborts with.
|
|
56
|
+
*
|
|
57
|
+
* The payload is JSON rather than delimited fields because a node id may
|
|
58
|
+
* contain a colon, and a positional encoding that breaks on user data is the
|
|
59
|
+
* kind of bug that only shows up in someone else's graph.
|
|
60
|
+
*/
|
|
61
|
+
declare function encodePause(signal: PauseSignal): string;
|
|
62
|
+
/**
|
|
63
|
+
* Decode a run's error reason into a pause, or null if it was a real failure.
|
|
64
|
+
*
|
|
65
|
+
* This is the whole contract from a runner's side: call it on `result.error`,
|
|
66
|
+
* and if it returns non-null, persist the run as waiting on `signal.nodeId`
|
|
67
|
+
* instead of failing it. Accepts the legacy prefixes, so a runner written
|
|
68
|
+
* against this handles runs that paused under an older version.
|
|
69
|
+
*/
|
|
70
|
+
declare function decodePause(reason: string | null | undefined): PauseSignal | null;
|
|
71
|
+
/** True when a run's error reason is actually a pause. */
|
|
72
|
+
declare function isPause(reason: string | null | undefined): boolean;
|
|
73
|
+
/**
|
|
74
|
+
* Abort the current node as a pause.
|
|
75
|
+
*
|
|
76
|
+
* Called from inside an executor with its own context. Node authors should
|
|
77
|
+
* reach for this rather than hand-encoding a reason, so the format stays ours
|
|
78
|
+
* to change:
|
|
79
|
+
*
|
|
80
|
+
* ```ts
|
|
81
|
+
* const values = ctx.inputs.values;
|
|
82
|
+
* if (values === undefined) pauseForHuman(ctx, "input", { fields });
|
|
83
|
+
* return values;
|
|
84
|
+
* ```
|
|
85
|
+
*
|
|
86
|
+
* Note the `undefined` check — an empty submission (`{}`) is a real answer and
|
|
87
|
+
* must resume. Truthiness here pauses forever on an empty form.
|
|
88
|
+
*/
|
|
89
|
+
declare function pauseForHuman(ctx: {
|
|
90
|
+
node: {
|
|
91
|
+
id: string;
|
|
92
|
+
};
|
|
93
|
+
abort: (reason?: string) => never;
|
|
94
|
+
}, awaiting: PauseAwaiting, detail?: unknown): never;
|
|
95
|
+
|
|
96
|
+
export { LEGACY_PAUSE_PREFIXES as L, type PauseAwaiting as P, PAUSE_PREFIX as a, type PauseSignal as b, decodePause as d, encodePause as e, isPause as i, pauseForHuman as p };
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The human-pause contract.
|
|
3
|
+
*
|
|
4
|
+
* A workflow that waits for a person is not an error, but it travels the same
|
|
5
|
+
* channel as one: the executor aborts, the engine records a reason string, and
|
|
6
|
+
* the durable runner decides whether that string meant "failed" or "waiting".
|
|
7
|
+
*
|
|
8
|
+
* That seam existed before this module, as two `str_starts_with` checks in the
|
|
9
|
+
* Laravel run job against constants owned by two BUILTIN executors. It worked,
|
|
10
|
+
* and it was invisible: a third-party human-input node had no way to announce
|
|
11
|
+
* that it pauses, and nothing stopped a refactor from removing the mechanism
|
|
12
|
+
* out from under published packages. Reported by the MOIC Suite consumer, who
|
|
13
|
+
* needed exactly that and had to reach for a private constant to get it.
|
|
14
|
+
*
|
|
15
|
+
* So the encoding is now public, typed, and versioned by prefix rather than
|
|
16
|
+
* implied. The wire format stays a plain string on purpose — it survives the
|
|
17
|
+
* existing abort → `RunResult.error` path unchanged, crosses a queue boundary,
|
|
18
|
+
* and decodes identically in PHP, none of which a thrown class would do.
|
|
19
|
+
*
|
|
20
|
+
* @see decodePause — the one function a durable runner needs.
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* What the run is waiting for.
|
|
24
|
+
*
|
|
25
|
+
* `approval` and `input` are the shapes both runtimes ship. The type stays open
|
|
26
|
+
* because the whole point is that a marketplace node can define its own —
|
|
27
|
+
* a signature step, a payment confirmation, a review queue — and a runner that
|
|
28
|
+
* does not recognise one should report it rather than guess.
|
|
29
|
+
*/
|
|
30
|
+
type PauseAwaiting = "approval" | "input" | (string & {});
|
|
31
|
+
/** A run halted, waiting for a person. */
|
|
32
|
+
type PauseSignal = {
|
|
33
|
+
/** The node that paused — where a submission gets injected on resume. */
|
|
34
|
+
nodeId: string;
|
|
35
|
+
awaiting: PauseAwaiting;
|
|
36
|
+
/**
|
|
37
|
+
* Kind-supplied context for whoever renders the wait — a form schema, the
|
|
38
|
+
* question being asked, a diff to approve. Must be JSON-serializable: it
|
|
39
|
+
* crosses a queue boundary and, for durable runs, a database column.
|
|
40
|
+
*/
|
|
41
|
+
detail?: unknown;
|
|
42
|
+
};
|
|
43
|
+
/** Marks a reason string as a pause rather than a failure. */
|
|
44
|
+
declare const PAUSE_PREFIX = "fancy-flow:pause:";
|
|
45
|
+
/**
|
|
46
|
+
* Reason prefixes shipped before this contract, kept decodable forever.
|
|
47
|
+
*
|
|
48
|
+
* These are what `DurableApprovalExecutor` and `DurableUserInputExecutor`
|
|
49
|
+
* emitted, and they are written into the `error` column of every run that
|
|
50
|
+
* paused under an older version. Dropping them would strand those runs
|
|
51
|
+
* mid-flight — a resume path that only works for new runs is not a resume path.
|
|
52
|
+
*/
|
|
53
|
+
declare const LEGACY_PAUSE_PREFIXES: ReadonlyArray<readonly [string, PauseAwaiting]>;
|
|
54
|
+
/**
|
|
55
|
+
* Encode a pause as the reason string an executor aborts with.
|
|
56
|
+
*
|
|
57
|
+
* The payload is JSON rather than delimited fields because a node id may
|
|
58
|
+
* contain a colon, and a positional encoding that breaks on user data is the
|
|
59
|
+
* kind of bug that only shows up in someone else's graph.
|
|
60
|
+
*/
|
|
61
|
+
declare function encodePause(signal: PauseSignal): string;
|
|
62
|
+
/**
|
|
63
|
+
* Decode a run's error reason into a pause, or null if it was a real failure.
|
|
64
|
+
*
|
|
65
|
+
* This is the whole contract from a runner's side: call it on `result.error`,
|
|
66
|
+
* and if it returns non-null, persist the run as waiting on `signal.nodeId`
|
|
67
|
+
* instead of failing it. Accepts the legacy prefixes, so a runner written
|
|
68
|
+
* against this handles runs that paused under an older version.
|
|
69
|
+
*/
|
|
70
|
+
declare function decodePause(reason: string | null | undefined): PauseSignal | null;
|
|
71
|
+
/** True when a run's error reason is actually a pause. */
|
|
72
|
+
declare function isPause(reason: string | null | undefined): boolean;
|
|
73
|
+
/**
|
|
74
|
+
* Abort the current node as a pause.
|
|
75
|
+
*
|
|
76
|
+
* Called from inside an executor with its own context. Node authors should
|
|
77
|
+
* reach for this rather than hand-encoding a reason, so the format stays ours
|
|
78
|
+
* to change:
|
|
79
|
+
*
|
|
80
|
+
* ```ts
|
|
81
|
+
* const values = ctx.inputs.values;
|
|
82
|
+
* if (values === undefined) pauseForHuman(ctx, "input", { fields });
|
|
83
|
+
* return values;
|
|
84
|
+
* ```
|
|
85
|
+
*
|
|
86
|
+
* Note the `undefined` check — an empty submission (`{}`) is a real answer and
|
|
87
|
+
* must resume. Truthiness here pauses forever on an empty form.
|
|
88
|
+
*/
|
|
89
|
+
declare function pauseForHuman(ctx: {
|
|
90
|
+
node: {
|
|
91
|
+
id: string;
|
|
92
|
+
};
|
|
93
|
+
abort: (reason?: string) => never;
|
|
94
|
+
}, awaiting: PauseAwaiting, detail?: unknown): never;
|
|
95
|
+
|
|
96
|
+
export { LEGACY_PAUSE_PREFIXES as L, type PauseAwaiting as P, PAUSE_PREFIX as a, type PauseSignal as b, decodePause as d, encodePause as e, isPause as i, pauseForHuman as p };
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { a as NodeKindDefinition, P as PortSpec } from '../types-
|
|
2
|
-
export { C as ConfigField, b as CredentialConfigField, D as DocumentConfigField, E as ExpressionConfigField, J as JsonConfigField, K as KeyValueConfigField, N as NodeCategory, c as NumberConfigField, R as RenderBodyContext, d as RepeaterConfigField, e as RepeaterRowField, S as SelectConfigField, f as SwitchConfigField, T as TextConfigField, g as TextareaConfigField } from '../types-
|
|
3
|
-
import {
|
|
4
|
-
import { b as LlmRoute } from '../capabilities-
|
|
5
|
-
export { C as CapabilityId, a as LlmClient, c as LlmRouteChoice, L as LlmRouteRequest, W as WorkflowResolver, d as capabilityStatus, g as getLlmClient, e as getWorkflowResolver, r as registerLlmClient, f as registerWorkflowResolver } from '../capabilities-
|
|
1
|
+
import { a as NodeKindDefinition, P as PortSpec } from '../types-D_jOR3Z2.cjs';
|
|
2
|
+
export { C as ConfigField, b as CredentialConfigField, D as DocumentConfigField, E as ExpressionConfigField, J as JsonConfigField, K as KeyValueConfigField, N as NodeCategory, c as NumberConfigField, R as RenderBodyContext, d as RepeaterConfigField, e as RepeaterRowField, S as SelectConfigField, f as SwitchConfigField, T as TextConfigField, g as TextareaConfigField } from '../types-D_jOR3Z2.cjs';
|
|
3
|
+
import { b as FlowNode, P as PortDescriptor, N as NodeExecutor } from '../types-sOmpCitB.cjs';
|
|
4
|
+
import { b as LlmRoute } from '../capabilities-BEbLqnJU.cjs';
|
|
5
|
+
export { C as CapabilityId, a as LlmClient, c as LlmRouteChoice, L as LlmRouteRequest, W as WorkflowResolver, d as capabilityStatus, g as getLlmClient, e as getWorkflowResolver, r as registerLlmClient, f as registerWorkflowResolver } from '../capabilities-BEbLqnJU.cjs';
|
|
6
|
+
export { L as LEGACY_PAUSE_PREFIXES, a as PAUSE_PREFIX, P as PauseAwaiting, b as PauseSignal, d as decodePause, e as encodePause, i as isPause, p as pauseForHuman } from '../pause-9iT4tCEV.cjs';
|
|
6
7
|
import * as react from 'react';
|
|
7
8
|
import { ComponentType, ReactNode } from 'react';
|
|
8
9
|
import { NodeProps, NodeTypes } from '@xyflow/react';
|
|
@@ -98,7 +99,7 @@ declare function declaredRoutes(config: Record<string, unknown>): LlmRoute[];
|
|
|
98
99
|
* route, and always loudly.
|
|
99
100
|
*/
|
|
100
101
|
declare function resolveFallbackPort(routes: LlmRoute[], fallbackEnabled: boolean): string;
|
|
101
|
-
declare const
|
|
102
|
+
declare const llmRouterExecutor: NodeExecutor;
|
|
102
103
|
|
|
103
104
|
/**
|
|
104
105
|
* Rich user input — the injection point.
|
|
@@ -230,4 +231,4 @@ declare const BUILTIN_KINDS: NodeKindDefinition[];
|
|
|
230
231
|
*/
|
|
231
232
|
declare function buildNodeTypes(): NodeTypes;
|
|
232
233
|
|
|
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 };
|
|
234
|
+
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/index.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { a as NodeKindDefinition, P as PortSpec } from '../types-
|
|
2
|
-
export { C as ConfigField, b as CredentialConfigField, D as DocumentConfigField, E as ExpressionConfigField, J as JsonConfigField, K as KeyValueConfigField, N as NodeCategory, c as NumberConfigField, R as RenderBodyContext, d as RepeaterConfigField, e as RepeaterRowField, S as SelectConfigField, f as SwitchConfigField, T as TextConfigField, g as TextareaConfigField } from '../types-
|
|
3
|
-
import {
|
|
4
|
-
import { b as LlmRoute } from '../capabilities-
|
|
5
|
-
export { C as CapabilityId, a as LlmClient, c as LlmRouteChoice, L as LlmRouteRequest, W as WorkflowResolver, d as capabilityStatus, g as getLlmClient, e as getWorkflowResolver, r as registerLlmClient, f as registerWorkflowResolver } from '../capabilities-
|
|
1
|
+
import { a as NodeKindDefinition, P as PortSpec } from '../types-NerkPtHS.js';
|
|
2
|
+
export { C as ConfigField, b as CredentialConfigField, D as DocumentConfigField, E as ExpressionConfigField, J as JsonConfigField, K as KeyValueConfigField, N as NodeCategory, c as NumberConfigField, R as RenderBodyContext, d as RepeaterConfigField, e as RepeaterRowField, S as SelectConfigField, f as SwitchConfigField, T as TextConfigField, g as TextareaConfigField } from '../types-NerkPtHS.js';
|
|
3
|
+
import { b as FlowNode, P as PortDescriptor, N as NodeExecutor } from '../types-sOmpCitB.js';
|
|
4
|
+
import { b as LlmRoute } from '../capabilities-CI3gw0C7.js';
|
|
5
|
+
export { C as CapabilityId, a as LlmClient, c as LlmRouteChoice, L as LlmRouteRequest, W as WorkflowResolver, d as capabilityStatus, g as getLlmClient, e as getWorkflowResolver, r as registerLlmClient, f as registerWorkflowResolver } from '../capabilities-CI3gw0C7.js';
|
|
6
|
+
export { L as LEGACY_PAUSE_PREFIXES, a as PAUSE_PREFIX, P as PauseAwaiting, b as PauseSignal, d as decodePause, e as encodePause, i as isPause, p as pauseForHuman } from '../pause-9iT4tCEV.js';
|
|
6
7
|
import * as react from 'react';
|
|
7
8
|
import { ComponentType, ReactNode } from 'react';
|
|
8
9
|
import { NodeProps, NodeTypes } from '@xyflow/react';
|
|
@@ -98,7 +99,7 @@ declare function declaredRoutes(config: Record<string, unknown>): LlmRoute[];
|
|
|
98
99
|
* route, and always loudly.
|
|
99
100
|
*/
|
|
100
101
|
declare function resolveFallbackPort(routes: LlmRoute[], fallbackEnabled: boolean): string;
|
|
101
|
-
declare const
|
|
102
|
+
declare const llmRouterExecutor: NodeExecutor;
|
|
102
103
|
|
|
103
104
|
/**
|
|
104
105
|
* Rich user input — the injection point.
|
|
@@ -230,4 +231,4 @@ declare const BUILTIN_KINDS: NodeKindDefinition[];
|
|
|
230
231
|
*/
|
|
231
232
|
declare function buildNodeTypes(): NodeTypes;
|
|
232
233
|
|
|
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 };
|
|
234
|
+
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
|
@@ -66,6 +66,42 @@ function capabilityStatus() {
|
|
|
66
66
|
};
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
// src/registry/pause.ts
|
|
70
|
+
var PAUSE_PREFIX = "fancy-flow:pause:";
|
|
71
|
+
var LEGACY_PAUSE_PREFIXES = [
|
|
72
|
+
["awaiting-approval:", "approval"],
|
|
73
|
+
["awaiting-input:", "input"]
|
|
74
|
+
];
|
|
75
|
+
function encodePause(signal) {
|
|
76
|
+
const { nodeId, awaiting, detail } = signal;
|
|
77
|
+
return PAUSE_PREFIX + JSON.stringify(detail === void 0 ? { nodeId, awaiting } : { nodeId, awaiting, detail });
|
|
78
|
+
}
|
|
79
|
+
function decodePause(reason) {
|
|
80
|
+
if (typeof reason !== "string") return null;
|
|
81
|
+
if (reason.startsWith(PAUSE_PREFIX)) {
|
|
82
|
+
const body = reason.slice(PAUSE_PREFIX.length);
|
|
83
|
+
try {
|
|
84
|
+
const parsed = JSON.parse(body);
|
|
85
|
+
if (typeof parsed?.nodeId !== "string" || typeof parsed?.awaiting !== "string") return null;
|
|
86
|
+
return "detail" in parsed ? { nodeId: parsed.nodeId, awaiting: parsed.awaiting, detail: parsed.detail } : { nodeId: parsed.nodeId, awaiting: parsed.awaiting };
|
|
87
|
+
} catch {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
for (const [prefix, awaiting] of LEGACY_PAUSE_PREFIXES) {
|
|
92
|
+
if (reason.startsWith(prefix)) {
|
|
93
|
+
return { nodeId: reason.slice(prefix.length), awaiting };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
function isPause(reason) {
|
|
99
|
+
return decodePause(reason) !== null;
|
|
100
|
+
}
|
|
101
|
+
function pauseForHuman(ctx, awaiting, detail) {
|
|
102
|
+
return ctx.abort(encodePause({ nodeId: ctx.node.id, awaiting, detail }));
|
|
103
|
+
}
|
|
104
|
+
|
|
69
105
|
// src/registry/registry.ts
|
|
70
106
|
var kinds = /* @__PURE__ */ new Map();
|
|
71
107
|
var aliases = /* @__PURE__ */ new Map();
|
|
@@ -431,7 +467,7 @@ var subflowExecutor = async (ctx) => {
|
|
|
431
467
|
return { __port: "out", value: result.outputs };
|
|
432
468
|
};
|
|
433
469
|
|
|
434
|
-
// src/registry/llm-
|
|
470
|
+
// src/registry/llm-router.ts
|
|
435
471
|
function declaredRoutes(config) {
|
|
436
472
|
const raw = config.routes;
|
|
437
473
|
if (!Array.isArray(raw)) return [];
|
|
@@ -441,11 +477,11 @@ function resolveFallbackPort(routes, fallbackEnabled) {
|
|
|
441
477
|
if (fallbackEnabled) return "fallback";
|
|
442
478
|
return routes[0]?.port ?? "out";
|
|
443
479
|
}
|
|
444
|
-
var
|
|
480
|
+
var llmRouterExecutor = async (ctx) => {
|
|
445
481
|
const config = ctx.node.data?.config ?? {};
|
|
446
482
|
const routes = declaredRoutes(config);
|
|
447
483
|
if (routes.length === 0) {
|
|
448
|
-
ctx.abort("
|
|
484
|
+
ctx.abort("llm_router has no routes configured");
|
|
449
485
|
}
|
|
450
486
|
const client = getLlmClient();
|
|
451
487
|
if (!client) {
|
|
@@ -471,7 +507,7 @@ var llmBranchExecutor = async (ctx) => {
|
|
|
471
507
|
type: "log",
|
|
472
508
|
nodeId: ctx.node.id,
|
|
473
509
|
level: "warn",
|
|
474
|
-
message: `
|
|
510
|
+
message: `llm_router: model returned "${port || "(nothing)"}", which is not a declared route. Routing to "${safe}".`
|
|
475
511
|
});
|
|
476
512
|
reason = reason ?? `unrecognised route "${port}"`;
|
|
477
513
|
port = safe;
|
|
@@ -9636,6 +9672,7 @@ var KINDS = [
|
|
|
9636
9672
|
{
|
|
9637
9673
|
name: "@particle-academy/user_input",
|
|
9638
9674
|
aliases: ["user_input", "@fancy/user_input"],
|
|
9675
|
+
pausesForHuman: "input",
|
|
9639
9676
|
category: "human",
|
|
9640
9677
|
label: "User Input",
|
|
9641
9678
|
description: "Pause the flow until the user submits the configured form.",
|
|
@@ -9677,6 +9714,7 @@ var KINDS = [
|
|
|
9677
9714
|
{
|
|
9678
9715
|
name: "@particle-academy/rich_user_input",
|
|
9679
9716
|
aliases: ["rich_user_input", "@fancy/rich_user_input"],
|
|
9717
|
+
pausesForHuman: "input",
|
|
9680
9718
|
category: "human",
|
|
9681
9719
|
label: "Rich User Input",
|
|
9682
9720
|
description: "Pause the flow on a fully authored page \u2014 content, required reading, multi-section forms.",
|
|
@@ -9734,10 +9772,13 @@ var KINDS = [
|
|
|
9734
9772
|
description: "Streaming adds a second port so a parent can show progress instead of a spinner."
|
|
9735
9773
|
},
|
|
9736
9774
|
{
|
|
9737
|
-
type: "
|
|
9775
|
+
type: "keyvalue",
|
|
9738
9776
|
key: "inputs",
|
|
9739
9777
|
label: "Input mapping",
|
|
9740
|
-
description: "
|
|
9778
|
+
description: "Values handed to the child's entry points. Omit to pass this node's inputs straight through.",
|
|
9779
|
+
keyLabel: "Name",
|
|
9780
|
+
valueLabel: "Value",
|
|
9781
|
+
addLabel: "Add input"
|
|
9741
9782
|
},
|
|
9742
9783
|
{
|
|
9743
9784
|
type: "number",
|
|
@@ -9761,7 +9802,57 @@ var KINDS = [
|
|
|
9761
9802
|
inputs: [{ id: "in" }],
|
|
9762
9803
|
outputs: [{ id: "true", label: "true" }, { id: "false", label: "false" }],
|
|
9763
9804
|
configSchema: [
|
|
9764
|
-
{
|
|
9805
|
+
{
|
|
9806
|
+
type: "select",
|
|
9807
|
+
key: "match",
|
|
9808
|
+
label: "Match",
|
|
9809
|
+
default: "all",
|
|
9810
|
+
options: [
|
|
9811
|
+
{ value: "all", label: "All conditions (AND)" },
|
|
9812
|
+
{ value: "any", label: "Any condition (OR)" }
|
|
9813
|
+
]
|
|
9814
|
+
},
|
|
9815
|
+
{
|
|
9816
|
+
type: "repeater",
|
|
9817
|
+
key: "conditions",
|
|
9818
|
+
label: "Conditions",
|
|
9819
|
+
description: "Routes to `true` when these match, otherwise `false`.",
|
|
9820
|
+
titleKey: "left",
|
|
9821
|
+
addLabel: "Add condition",
|
|
9822
|
+
minItems: 1,
|
|
9823
|
+
fields: [
|
|
9824
|
+
{ type: "expression", key: "left", label: "Value", example: "{{ $json.status }}", required: true },
|
|
9825
|
+
{
|
|
9826
|
+
type: "select",
|
|
9827
|
+
key: "operator",
|
|
9828
|
+
label: "Is",
|
|
9829
|
+
default: "eq",
|
|
9830
|
+
options: [
|
|
9831
|
+
{ value: "eq", label: "equal to" },
|
|
9832
|
+
{ value: "neq", label: "not equal to" },
|
|
9833
|
+
{ value: "contains", label: "contains" },
|
|
9834
|
+
{ value: "not_contains", label: "does not contain" },
|
|
9835
|
+
{ value: "gt", label: "greater than" },
|
|
9836
|
+
{ value: "gte", label: "greater than or equal to" },
|
|
9837
|
+
{ value: "lt", label: "less than" },
|
|
9838
|
+
{ value: "lte", label: "less than or equal to" },
|
|
9839
|
+
{ value: "truthy", label: "true" },
|
|
9840
|
+
{ value: "falsy", label: "false" },
|
|
9841
|
+
{ value: "empty", label: "empty" },
|
|
9842
|
+
{ value: "not_empty", label: "not empty" }
|
|
9843
|
+
]
|
|
9844
|
+
},
|
|
9845
|
+
{ type: "text", key: "right", label: "Compared to", placeholder: "active" }
|
|
9846
|
+
],
|
|
9847
|
+
default: [{ left: "", operator: "eq", right: "" }]
|
|
9848
|
+
},
|
|
9849
|
+
{
|
|
9850
|
+
type: "expression",
|
|
9851
|
+
key: "condition",
|
|
9852
|
+
label: "Raw expression (advanced)",
|
|
9853
|
+
example: "{{ $json.active && $json.score > 10 }}",
|
|
9854
|
+
description: "Escape hatch for logic the builder can't express. Overrides the conditions above when set."
|
|
9855
|
+
}
|
|
9765
9856
|
]
|
|
9766
9857
|
},
|
|
9767
9858
|
{
|
|
@@ -9851,12 +9942,35 @@ var KINDS = [
|
|
|
9851
9942
|
description: "Reshape data with an expression.",
|
|
9852
9943
|
icon: "\u0192",
|
|
9853
9944
|
configSchema: [
|
|
9945
|
+
{
|
|
9946
|
+
type: "select",
|
|
9947
|
+
key: "mode",
|
|
9948
|
+
label: "Build the output",
|
|
9949
|
+
default: "fields",
|
|
9950
|
+
options: [
|
|
9951
|
+
{ value: "fields", label: "Field by field" },
|
|
9952
|
+
{ value: "expression", label: "One expression" }
|
|
9953
|
+
]
|
|
9954
|
+
},
|
|
9955
|
+
{
|
|
9956
|
+
type: "repeater",
|
|
9957
|
+
key: "fields",
|
|
9958
|
+
label: "Output fields",
|
|
9959
|
+
description: "Each row becomes a key on the result.",
|
|
9960
|
+
titleKey: "key",
|
|
9961
|
+
addLabel: "Add field",
|
|
9962
|
+
fields: [
|
|
9963
|
+
{ type: "text", key: "key", label: "Key", required: true, placeholder: "name" },
|
|
9964
|
+
{ type: "expression", key: "value", label: "Value", example: "{{ $json.first }}", required: true }
|
|
9965
|
+
],
|
|
9966
|
+
default: [{ key: "", value: "" }]
|
|
9967
|
+
},
|
|
9854
9968
|
{
|
|
9855
9969
|
type: "expression",
|
|
9856
9970
|
key: "expression",
|
|
9857
|
-
label: "Expression",
|
|
9971
|
+
label: "Expression (advanced)",
|
|
9858
9972
|
example: "{{ { id: $json.id, name: $json.first + ' ' + $json.last } }}",
|
|
9859
|
-
|
|
9973
|
+
description: "Used when the mode above is set to one expression."
|
|
9860
9974
|
}
|
|
9861
9975
|
]
|
|
9862
9976
|
},
|
|
@@ -9906,7 +10020,15 @@ var KINDS = [
|
|
|
9906
10020
|
},
|
|
9907
10021
|
{ type: "text", key: "table", label: "Table / collection", required: true },
|
|
9908
10022
|
{ type: "text", key: "key", label: "Key" },
|
|
9909
|
-
{
|
|
10023
|
+
{
|
|
10024
|
+
type: "keyvalue",
|
|
10025
|
+
key: "where",
|
|
10026
|
+
label: "Where",
|
|
10027
|
+
description: "Field/value pairs to match. For query and list operations.",
|
|
10028
|
+
keyLabel: "Field",
|
|
10029
|
+
valueLabel: "Equals",
|
|
10030
|
+
addLabel: "Add filter"
|
|
10031
|
+
},
|
|
9910
10032
|
{ type: "expression", key: "value", label: "Value (set only)", example: "{{ $json }}" },
|
|
9911
10033
|
{ type: "credential", key: "store", label: "Data store", credentialType: "data_store" }
|
|
9912
10034
|
]
|
|
@@ -9948,13 +10070,32 @@ var KINDS = [
|
|
|
9948
10070
|
{ type: "expression", key: "prompt", label: "User prompt", example: "{{ $json.question }}", required: true },
|
|
9949
10071
|
{ type: "number", key: "temperature", label: "Temperature", min: 0, max: 2, step: 0.1, default: 0.7 },
|
|
9950
10072
|
{ type: "number", key: "max_tokens", label: "Max tokens", min: 1, max: 8192, default: 1024 },
|
|
9951
|
-
{
|
|
10073
|
+
{
|
|
10074
|
+
type: "repeater",
|
|
10075
|
+
key: "tools",
|
|
10076
|
+
label: "Tools",
|
|
10077
|
+
description: "Tools the model may call.",
|
|
10078
|
+
titleKey: "name",
|
|
10079
|
+
addLabel: "Add tool",
|
|
10080
|
+
fields: [
|
|
10081
|
+
{ type: "text", key: "name", label: "Name", required: true, placeholder: "search_index" },
|
|
10082
|
+
{ type: "text", key: "description", label: "When to use it" },
|
|
10083
|
+
{
|
|
10084
|
+
type: "json",
|
|
10085
|
+
key: "input_schema",
|
|
10086
|
+
label: "Input schema",
|
|
10087
|
+
description: "JSON Schema for the tool's arguments."
|
|
10088
|
+
}
|
|
10089
|
+
]
|
|
10090
|
+
},
|
|
9952
10091
|
{ type: "credential", key: "credential", label: "API credential", credentialType: "llm_credential" }
|
|
9953
10092
|
]
|
|
9954
10093
|
},
|
|
9955
10094
|
{
|
|
9956
|
-
name: "@particle-academy/
|
|
9957
|
-
|
|
10095
|
+
name: "@particle-academy/llm_router",
|
|
10096
|
+
// Every id this node has ever shipped under keeps resolving — MOIC's saved
|
|
10097
|
+
// flows carry the bare `llm_branch`.
|
|
10098
|
+
aliases: ["llm_router", "llm_branch", "@fancy/llm_branch", "@fancy/llm_router"],
|
|
9958
10099
|
category: "ai",
|
|
9959
10100
|
label: "LLM Router",
|
|
9960
10101
|
description: "Let a model choose which route the flow takes.",
|
|
@@ -9966,7 +10107,7 @@ var KINDS = [
|
|
|
9966
10107
|
// A shuttle, not an engine: it carries the routes out to whatever LLM
|
|
9967
10108
|
// client the host registered and carries the choice back. No provider SDK
|
|
9968
10109
|
// reaches core, so this stays a builtin without adding a dependency.
|
|
9969
|
-
executor:
|
|
10110
|
+
executor: llmRouterExecutor,
|
|
9970
10111
|
configSchema: [
|
|
9971
10112
|
{
|
|
9972
10113
|
type: "textarea",
|
|
@@ -10063,7 +10204,17 @@ var KINDS = [
|
|
|
10063
10204
|
configSchema: [
|
|
10064
10205
|
...HTTP_METHODS,
|
|
10065
10206
|
{ type: "text", key: "url", label: "URL", placeholder: "https://api.example.com/...", required: true },
|
|
10066
|
-
{
|
|
10207
|
+
{
|
|
10208
|
+
type: "keyvalue",
|
|
10209
|
+
key: "headers",
|
|
10210
|
+
label: "Headers",
|
|
10211
|
+
keyLabel: "Header",
|
|
10212
|
+
valueLabel: "Value",
|
|
10213
|
+
keyPlaceholder: "content-type",
|
|
10214
|
+
valuePlaceholder: "application/json",
|
|
10215
|
+
addLabel: "Add header",
|
|
10216
|
+
default: { "content-type": "application/json" }
|
|
10217
|
+
},
|
|
10067
10218
|
{ type: "json", key: "body", label: "Body" },
|
|
10068
10219
|
{ type: "credential", key: "auth", label: "Auth", credentialType: "api_credential" }
|
|
10069
10220
|
]
|
|
@@ -10077,7 +10228,14 @@ var KINDS = [
|
|
|
10077
10228
|
icon: "\u2197",
|
|
10078
10229
|
configSchema: [
|
|
10079
10230
|
{ type: "text", key: "url", label: "URL", required: true },
|
|
10080
|
-
{
|
|
10231
|
+
{
|
|
10232
|
+
type: "keyvalue",
|
|
10233
|
+
key: "headers",
|
|
10234
|
+
label: "Headers",
|
|
10235
|
+
keyLabel: "Header",
|
|
10236
|
+
valueLabel: "Value",
|
|
10237
|
+
addLabel: "Add header"
|
|
10238
|
+
},
|
|
10081
10239
|
{ type: "expression", key: "payload", label: "Payload", required: true, example: "{{ $json }}" }
|
|
10082
10240
|
]
|
|
10083
10241
|
},
|
|
@@ -10085,6 +10243,7 @@ var KINDS = [
|
|
|
10085
10243
|
{
|
|
10086
10244
|
name: "@particle-academy/human_approval",
|
|
10087
10245
|
aliases: ["human_approval", "@fancy/human_approval"],
|
|
10246
|
+
pausesForHuman: "approval",
|
|
10088
10247
|
category: "human",
|
|
10089
10248
|
label: "Human Approval",
|
|
10090
10249
|
description: "Pause until a human approves or denies.",
|
|
@@ -10169,24 +10328,31 @@ function buildNodeTypes() {
|
|
|
10169
10328
|
|
|
10170
10329
|
exports.BUILTIN_KINDS = BUILTIN_KINDS;
|
|
10171
10330
|
exports.DEFAULT_MAX_DEPTH = DEFAULT_MAX_DEPTH;
|
|
10331
|
+
exports.LEGACY_PAUSE_PREFIXES = LEGACY_PAUSE_PREFIXES;
|
|
10332
|
+
exports.PAUSE_PREFIX = PAUSE_PREFIX;
|
|
10172
10333
|
exports.RegistryNode = RegistryNode;
|
|
10173
10334
|
exports.RichInputPreview = RichInputPreview;
|
|
10174
10335
|
exports.buildNodeTypes = buildNodeTypes;
|
|
10175
10336
|
exports.capabilityStatus = capabilityStatus;
|
|
10176
10337
|
exports.categoryAccent = categoryAccent;
|
|
10177
10338
|
exports.declaredRoutes = declaredRoutes;
|
|
10339
|
+
exports.decodePause = decodePause;
|
|
10178
10340
|
exports.defaultConfigFor = defaultConfigFor;
|
|
10341
|
+
exports.encodePause = encodePause;
|
|
10179
10342
|
exports.getLlmClient = getLlmClient;
|
|
10180
10343
|
exports.getNodeKind = getNodeKind;
|
|
10181
10344
|
exports.getRichInputAdapter = getRichInputAdapter;
|
|
10182
10345
|
exports.getWorkflowResolver = getWorkflowResolver;
|
|
10346
|
+
exports.isPause = isPause;
|
|
10183
10347
|
exports.isRichInputEnabled = isRichInputEnabled;
|
|
10184
10348
|
exports.kindIds = kindIds;
|
|
10185
10349
|
exports.listNodeKinds = listNodeKinds;
|
|
10186
|
-
exports.llmBranchExecutor =
|
|
10350
|
+
exports.llmBranchExecutor = llmRouterExecutor;
|
|
10351
|
+
exports.llmRouterExecutor = llmRouterExecutor;
|
|
10187
10352
|
exports.nodeConfig = nodeConfig;
|
|
10188
10353
|
exports.onNodeKindsChanged = onNodeKindsChanged;
|
|
10189
10354
|
exports.onRichInputAdapterChanged = onRichInputAdapterChanged;
|
|
10355
|
+
exports.pauseForHuman = pauseForHuman;
|
|
10190
10356
|
exports.registerBuiltinKinds = registerBuiltinKinds;
|
|
10191
10357
|
exports.registerLlmClient = registerLlmClient;
|
|
10192
10358
|
exports.registerNodeKind = registerNodeKind;
|