@particle-academy/fancy-flow 0.12.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/capabilities-B6r1Snfj.d.ts +77 -0
- package/dist/capabilities-D-V9Rxv1.d.cts +77 -0
- package/dist/{chunk-IK5DS5JP.js → chunk-7U3EP4Q5.js} +140 -54
- package/dist/chunk-7U3EP4Q5.js.map +1 -0
- package/dist/chunk-BB45F6S3.js +38 -0
- package/dist/chunk-BB45F6S3.js.map +1 -0
- package/dist/engine.d.cts +2 -2
- package/dist/engine.d.ts +2 -2
- package/dist/index.cjs +136 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -4
- package/dist/index.d.ts +5 -4
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/llm/vercel-ai.cjs +59 -0
- package/dist/llm/vercel-ai.cjs.map +1 -0
- package/dist/llm/vercel-ai.d.cts +59 -0
- package/dist/llm/vercel-ai.d.ts +59 -0
- package/dist/llm/vercel-ai.js +49 -0
- package/dist/llm/vercel-ai.js.map +1 -0
- package/dist/registry/index.d.cts +7 -79
- package/dist/registry/index.d.ts +7 -79
- package/dist/registry.cjs +138 -17
- package/dist/registry.cjs.map +1 -1
- package/dist/registry.js +2 -1
- package/dist/runtime/index.d.cts +1 -1
- package/dist/runtime/index.d.ts +1 -1
- package/dist/schema/index.d.cts +1 -1
- package/dist/schema/index.d.ts +1 -1
- package/dist/{types-DtXOwXjA.d.ts → types-CnnKPnpt.d.ts} +1 -1
- package/dist/{types-DnQ4TEHN.d.cts → types-H60tQAxr.d.cts} +1 -1
- package/dist/{types-Dg2REAz5.d.cts → types-fc0fFKkf.d.cts} +1 -1
- package/dist/{types-Dg2REAz5.d.ts → types-fc0fFKkf.d.ts} +1 -1
- package/dist/ux.d.cts +2 -2
- package/dist/ux.d.ts +2 -2
- package/package.json +19 -3
- package/dist/chunk-IK5DS5JP.js.map +0 -1
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { F as FlowGraph } from './types-fc0fFKkf.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Host capabilities — the services core nodes need but must never depend on.
|
|
5
|
+
*
|
|
6
|
+
* A node that imports a provider SDK forces every consumer to install it: a
|
|
7
|
+
* workflow app that never calls a model should not inherit an LLM dependency.
|
|
8
|
+
* So core declares the CONTRACT and the host supplies the implementation, the
|
|
9
|
+
* same arrangement `renderDocumentField` already uses for documents.
|
|
10
|
+
*
|
|
11
|
+
* That keeps opinionated nodes in core without their opinions: `llm_branch`
|
|
12
|
+
* ships the routing semantics, port derivation and config UI, while whichever
|
|
13
|
+
* client the host registers — Prism, an OpenAI SDK, a local model, a fake in a
|
|
14
|
+
* test — decides how the question actually gets asked.
|
|
15
|
+
*
|
|
16
|
+
* Registration is deliberately explicit and typed per capability rather than a
|
|
17
|
+
* stringly-keyed bag, so a missing one is a clear error at the seam instead of
|
|
18
|
+
* an undefined somewhere downstream.
|
|
19
|
+
*/
|
|
20
|
+
type LlmRoute = {
|
|
21
|
+
port: string;
|
|
22
|
+
description?: string;
|
|
23
|
+
};
|
|
24
|
+
type LlmRouteRequest = {
|
|
25
|
+
/** Optional framing for the decision. */
|
|
26
|
+
system?: string;
|
|
27
|
+
/** What the model is deciding about. */
|
|
28
|
+
prompt: string;
|
|
29
|
+
/** The ports it must choose between. */
|
|
30
|
+
routes: LlmRoute[];
|
|
31
|
+
provider?: string;
|
|
32
|
+
model?: string;
|
|
33
|
+
/** Host-resolved credential reference, never a raw key. */
|
|
34
|
+
credential?: string;
|
|
35
|
+
};
|
|
36
|
+
type LlmRouteChoice = {
|
|
37
|
+
/** Must be one of the requested route ports. */
|
|
38
|
+
port: string;
|
|
39
|
+
/** Why — carried down the chosen port so a run is explainable afterwards. */
|
|
40
|
+
reason?: string;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* The only thing core asks of an LLM: given routes, pick one.
|
|
44
|
+
*
|
|
45
|
+
* Deliberately not a general chat interface. A narrow contract is one a host
|
|
46
|
+
* can satisfy in a few lines over any SDK, and it keeps the choice
|
|
47
|
+
* machine-checkable — an implementation should constrain the model to the
|
|
48
|
+
* declared ports (structured output / enum) rather than parsing prose.
|
|
49
|
+
*/
|
|
50
|
+
type LlmClient = {
|
|
51
|
+
chooseRoute: (request: LlmRouteRequest) => Promise<LlmRouteChoice> | LlmRouteChoice;
|
|
52
|
+
};
|
|
53
|
+
/** Install the host's LLM client. Returns an unregister function. */
|
|
54
|
+
declare function registerLlmClient(client: LlmClient): () => void;
|
|
55
|
+
declare function getLlmClient(): LlmClient | null;
|
|
56
|
+
/**
|
|
57
|
+
* Resolve a workflow reference to a runnable graph.
|
|
58
|
+
*
|
|
59
|
+
* `subflow` names another workflow rather than embedding it, so the host owns
|
|
60
|
+
* where workflows live — a database, a file, an API. Returning null means "no
|
|
61
|
+
* such workflow", which the node reports as an error rather than silently
|
|
62
|
+
* running nothing.
|
|
63
|
+
*/
|
|
64
|
+
type WorkflowResolver = (ref: string) => Promise<FlowGraph | null> | FlowGraph | null;
|
|
65
|
+
/** Install the host's workflow resolver. Returns an unregister function. */
|
|
66
|
+
declare function registerWorkflowResolver(resolver: WorkflowResolver): () => void;
|
|
67
|
+
declare function getWorkflowResolver(): WorkflowResolver | null;
|
|
68
|
+
type CapabilityId = "llm" | "workflow_resolver" | "document";
|
|
69
|
+
/**
|
|
70
|
+
* Which capabilities are currently satisfied.
|
|
71
|
+
*
|
|
72
|
+
* Exists so a host (or the CLI, or an agent over MCP) can answer "what does
|
|
73
|
+
* this graph need that I haven't wired?" BEFORE a run fails halfway through.
|
|
74
|
+
*/
|
|
75
|
+
declare function capabilityStatus(): Record<CapabilityId, boolean>;
|
|
76
|
+
|
|
77
|
+
export { type CapabilityId as C, type LlmRouteRequest as L, type WorkflowResolver as W, type LlmClient as a, type LlmRoute as b, type LlmRouteChoice as c, capabilityStatus as d, getWorkflowResolver as e, registerWorkflowResolver as f, getLlmClient as g, registerLlmClient as r };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { F as FlowGraph } from './types-fc0fFKkf.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Host capabilities — the services core nodes need but must never depend on.
|
|
5
|
+
*
|
|
6
|
+
* A node that imports a provider SDK forces every consumer to install it: a
|
|
7
|
+
* workflow app that never calls a model should not inherit an LLM dependency.
|
|
8
|
+
* So core declares the CONTRACT and the host supplies the implementation, the
|
|
9
|
+
* same arrangement `renderDocumentField` already uses for documents.
|
|
10
|
+
*
|
|
11
|
+
* That keeps opinionated nodes in core without their opinions: `llm_branch`
|
|
12
|
+
* ships the routing semantics, port derivation and config UI, while whichever
|
|
13
|
+
* client the host registers — Prism, an OpenAI SDK, a local model, a fake in a
|
|
14
|
+
* test — decides how the question actually gets asked.
|
|
15
|
+
*
|
|
16
|
+
* Registration is deliberately explicit and typed per capability rather than a
|
|
17
|
+
* stringly-keyed bag, so a missing one is a clear error at the seam instead of
|
|
18
|
+
* an undefined somewhere downstream.
|
|
19
|
+
*/
|
|
20
|
+
type LlmRoute = {
|
|
21
|
+
port: string;
|
|
22
|
+
description?: string;
|
|
23
|
+
};
|
|
24
|
+
type LlmRouteRequest = {
|
|
25
|
+
/** Optional framing for the decision. */
|
|
26
|
+
system?: string;
|
|
27
|
+
/** What the model is deciding about. */
|
|
28
|
+
prompt: string;
|
|
29
|
+
/** The ports it must choose between. */
|
|
30
|
+
routes: LlmRoute[];
|
|
31
|
+
provider?: string;
|
|
32
|
+
model?: string;
|
|
33
|
+
/** Host-resolved credential reference, never a raw key. */
|
|
34
|
+
credential?: string;
|
|
35
|
+
};
|
|
36
|
+
type LlmRouteChoice = {
|
|
37
|
+
/** Must be one of the requested route ports. */
|
|
38
|
+
port: string;
|
|
39
|
+
/** Why — carried down the chosen port so a run is explainable afterwards. */
|
|
40
|
+
reason?: string;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* The only thing core asks of an LLM: given routes, pick one.
|
|
44
|
+
*
|
|
45
|
+
* Deliberately not a general chat interface. A narrow contract is one a host
|
|
46
|
+
* can satisfy in a few lines over any SDK, and it keeps the choice
|
|
47
|
+
* machine-checkable — an implementation should constrain the model to the
|
|
48
|
+
* declared ports (structured output / enum) rather than parsing prose.
|
|
49
|
+
*/
|
|
50
|
+
type LlmClient = {
|
|
51
|
+
chooseRoute: (request: LlmRouteRequest) => Promise<LlmRouteChoice> | LlmRouteChoice;
|
|
52
|
+
};
|
|
53
|
+
/** Install the host's LLM client. Returns an unregister function. */
|
|
54
|
+
declare function registerLlmClient(client: LlmClient): () => void;
|
|
55
|
+
declare function getLlmClient(): LlmClient | null;
|
|
56
|
+
/**
|
|
57
|
+
* Resolve a workflow reference to a runnable graph.
|
|
58
|
+
*
|
|
59
|
+
* `subflow` names another workflow rather than embedding it, so the host owns
|
|
60
|
+
* where workflows live — a database, a file, an API. Returning null means "no
|
|
61
|
+
* such workflow", which the node reports as an error rather than silently
|
|
62
|
+
* running nothing.
|
|
63
|
+
*/
|
|
64
|
+
type WorkflowResolver = (ref: string) => Promise<FlowGraph | null> | FlowGraph | null;
|
|
65
|
+
/** Install the host's workflow resolver. Returns an unregister function. */
|
|
66
|
+
declare function registerWorkflowResolver(resolver: WorkflowResolver): () => void;
|
|
67
|
+
declare function getWorkflowResolver(): WorkflowResolver | null;
|
|
68
|
+
type CapabilityId = "llm" | "workflow_resolver" | "document";
|
|
69
|
+
/**
|
|
70
|
+
* Which capabilities are currently satisfied.
|
|
71
|
+
*
|
|
72
|
+
* Exists so a host (or the CLI, or an agent over MCP) can answer "what does
|
|
73
|
+
* this graph need that I haven't wired?" BEFORE a run fails halfway through.
|
|
74
|
+
*/
|
|
75
|
+
declare function capabilityStatus(): Record<CapabilityId, boolean>;
|
|
76
|
+
|
|
77
|
+
export { type CapabilityId as C, type LlmRouteRequest as L, type WorkflowResolver as W, type LlmClient as a, type LlmRoute as b, type LlmRouteChoice as c, capabilityStatus as d, getWorkflowResolver as e, registerWorkflowResolver as f, getLlmClient as g, registerLlmClient as r };
|
|
@@ -3,44 +3,10 @@ import { runFlow } from './chunk-L4AX73Q6.js';
|
|
|
3
3
|
import { resolveNodePorts, nodeConfig } from './chunk-TITD5W4Y.js';
|
|
4
4
|
import { getNodeKind, categoryAccent, registerNodeKind, listNodeKinds, kindIds } from './chunk-U5F22BHV.js';
|
|
5
5
|
import { RichInputPreview } from './chunk-F5RPRB7A.js';
|
|
6
|
+
import { getWorkflowResolver, getLlmClient } from './chunk-BB45F6S3.js';
|
|
6
7
|
import { memo, useMemo, createElement } from 'react';
|
|
7
8
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
8
9
|
|
|
9
|
-
// src/registry/capabilities.ts
|
|
10
|
-
var llmClient = null;
|
|
11
|
-
function registerLlmClient(client) {
|
|
12
|
-
llmClient = client;
|
|
13
|
-
return () => {
|
|
14
|
-
if (llmClient === client) llmClient = null;
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
function getLlmClient() {
|
|
18
|
-
return llmClient;
|
|
19
|
-
}
|
|
20
|
-
var workflowResolver = null;
|
|
21
|
-
function registerWorkflowResolver(resolver) {
|
|
22
|
-
workflowResolver = resolver;
|
|
23
|
-
return () => {
|
|
24
|
-
if (workflowResolver === resolver) workflowResolver = null;
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
function getWorkflowResolver() {
|
|
28
|
-
return workflowResolver;
|
|
29
|
-
}
|
|
30
|
-
function capabilityStatus() {
|
|
31
|
-
let documentReady = false;
|
|
32
|
-
try {
|
|
33
|
-
documentReady = Boolean(globalThis.__fancyFlowDocumentAdapter);
|
|
34
|
-
} catch {
|
|
35
|
-
documentReady = false;
|
|
36
|
-
}
|
|
37
|
-
return {
|
|
38
|
-
llm: llmClient !== null,
|
|
39
|
-
workflow_resolver: workflowResolver !== null,
|
|
40
|
-
document: documentReady
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
|
|
44
10
|
// src/registry/subflow.ts
|
|
45
11
|
var DEFAULT_MAX_DEPTH = 8;
|
|
46
12
|
function subflowMode(config) {
|
|
@@ -110,7 +76,7 @@ var subflowExecutor = async (ctx) => {
|
|
|
110
76
|
return { __port: "out", value: result.outputs };
|
|
111
77
|
};
|
|
112
78
|
|
|
113
|
-
// src/registry/llm-
|
|
79
|
+
// src/registry/llm-router.ts
|
|
114
80
|
function declaredRoutes(config) {
|
|
115
81
|
const raw = config.routes;
|
|
116
82
|
if (!Array.isArray(raw)) return [];
|
|
@@ -120,11 +86,11 @@ function resolveFallbackPort(routes, fallbackEnabled) {
|
|
|
120
86
|
if (fallbackEnabled) return "fallback";
|
|
121
87
|
return routes[0]?.port ?? "out";
|
|
122
88
|
}
|
|
123
|
-
var
|
|
89
|
+
var llmRouterExecutor = async (ctx) => {
|
|
124
90
|
const config = ctx.node.data?.config ?? {};
|
|
125
91
|
const routes = declaredRoutes(config);
|
|
126
92
|
if (routes.length === 0) {
|
|
127
|
-
ctx.abort("
|
|
93
|
+
ctx.abort("llm_router has no routes configured");
|
|
128
94
|
}
|
|
129
95
|
const client = getLlmClient();
|
|
130
96
|
if (!client) {
|
|
@@ -150,7 +116,7 @@ var llmBranchExecutor = async (ctx) => {
|
|
|
150
116
|
type: "log",
|
|
151
117
|
nodeId: ctx.node.id,
|
|
152
118
|
level: "warn",
|
|
153
|
-
message: `
|
|
119
|
+
message: `llm_router: model returned "${port || "(nothing)"}", which is not a declared route. Routing to "${safe}".`
|
|
154
120
|
});
|
|
155
121
|
reason = reason ?? `unrecognised route "${port}"`;
|
|
156
122
|
port = safe;
|
|
@@ -464,10 +430,13 @@ var KINDS = [
|
|
|
464
430
|
description: "Streaming adds a second port so a parent can show progress instead of a spinner."
|
|
465
431
|
},
|
|
466
432
|
{
|
|
467
|
-
type: "
|
|
433
|
+
type: "keyvalue",
|
|
468
434
|
key: "inputs",
|
|
469
435
|
label: "Input mapping",
|
|
470
|
-
description: "
|
|
436
|
+
description: "Values handed to the child's entry points. Omit to pass this node's inputs straight through.",
|
|
437
|
+
keyLabel: "Name",
|
|
438
|
+
valueLabel: "Value",
|
|
439
|
+
addLabel: "Add input"
|
|
471
440
|
},
|
|
472
441
|
{
|
|
473
442
|
type: "number",
|
|
@@ -491,7 +460,57 @@ var KINDS = [
|
|
|
491
460
|
inputs: [{ id: "in" }],
|
|
492
461
|
outputs: [{ id: "true", label: "true" }, { id: "false", label: "false" }],
|
|
493
462
|
configSchema: [
|
|
494
|
-
{
|
|
463
|
+
{
|
|
464
|
+
type: "select",
|
|
465
|
+
key: "match",
|
|
466
|
+
label: "Match",
|
|
467
|
+
default: "all",
|
|
468
|
+
options: [
|
|
469
|
+
{ value: "all", label: "All conditions (AND)" },
|
|
470
|
+
{ value: "any", label: "Any condition (OR)" }
|
|
471
|
+
]
|
|
472
|
+
},
|
|
473
|
+
{
|
|
474
|
+
type: "repeater",
|
|
475
|
+
key: "conditions",
|
|
476
|
+
label: "Conditions",
|
|
477
|
+
description: "Routes to `true` when these match, otherwise `false`.",
|
|
478
|
+
titleKey: "left",
|
|
479
|
+
addLabel: "Add condition",
|
|
480
|
+
minItems: 1,
|
|
481
|
+
fields: [
|
|
482
|
+
{ type: "expression", key: "left", label: "Value", example: "{{ $json.status }}", required: true },
|
|
483
|
+
{
|
|
484
|
+
type: "select",
|
|
485
|
+
key: "operator",
|
|
486
|
+
label: "Is",
|
|
487
|
+
default: "eq",
|
|
488
|
+
options: [
|
|
489
|
+
{ value: "eq", label: "equal to" },
|
|
490
|
+
{ value: "neq", label: "not equal to" },
|
|
491
|
+
{ value: "contains", label: "contains" },
|
|
492
|
+
{ value: "not_contains", label: "does not contain" },
|
|
493
|
+
{ value: "gt", label: "greater than" },
|
|
494
|
+
{ value: "gte", label: "greater than or equal to" },
|
|
495
|
+
{ value: "lt", label: "less than" },
|
|
496
|
+
{ value: "lte", label: "less than or equal to" },
|
|
497
|
+
{ value: "truthy", label: "true" },
|
|
498
|
+
{ value: "falsy", label: "false" },
|
|
499
|
+
{ value: "empty", label: "empty" },
|
|
500
|
+
{ value: "not_empty", label: "not empty" }
|
|
501
|
+
]
|
|
502
|
+
},
|
|
503
|
+
{ type: "text", key: "right", label: "Compared to", placeholder: "active" }
|
|
504
|
+
],
|
|
505
|
+
default: [{ left: "", operator: "eq", right: "" }]
|
|
506
|
+
},
|
|
507
|
+
{
|
|
508
|
+
type: "expression",
|
|
509
|
+
key: "condition",
|
|
510
|
+
label: "Raw expression (advanced)",
|
|
511
|
+
example: "{{ $json.active && $json.score > 10 }}",
|
|
512
|
+
description: "Escape hatch for logic the builder can't express. Overrides the conditions above when set."
|
|
513
|
+
}
|
|
495
514
|
]
|
|
496
515
|
},
|
|
497
516
|
{
|
|
@@ -581,12 +600,35 @@ var KINDS = [
|
|
|
581
600
|
description: "Reshape data with an expression.",
|
|
582
601
|
icon: "\u0192",
|
|
583
602
|
configSchema: [
|
|
603
|
+
{
|
|
604
|
+
type: "select",
|
|
605
|
+
key: "mode",
|
|
606
|
+
label: "Build the output",
|
|
607
|
+
default: "fields",
|
|
608
|
+
options: [
|
|
609
|
+
{ value: "fields", label: "Field by field" },
|
|
610
|
+
{ value: "expression", label: "One expression" }
|
|
611
|
+
]
|
|
612
|
+
},
|
|
613
|
+
{
|
|
614
|
+
type: "repeater",
|
|
615
|
+
key: "fields",
|
|
616
|
+
label: "Output fields",
|
|
617
|
+
description: "Each row becomes a key on the result.",
|
|
618
|
+
titleKey: "key",
|
|
619
|
+
addLabel: "Add field",
|
|
620
|
+
fields: [
|
|
621
|
+
{ type: "text", key: "key", label: "Key", required: true, placeholder: "name" },
|
|
622
|
+
{ type: "expression", key: "value", label: "Value", example: "{{ $json.first }}", required: true }
|
|
623
|
+
],
|
|
624
|
+
default: [{ key: "", value: "" }]
|
|
625
|
+
},
|
|
584
626
|
{
|
|
585
627
|
type: "expression",
|
|
586
628
|
key: "expression",
|
|
587
|
-
label: "Expression",
|
|
629
|
+
label: "Expression (advanced)",
|
|
588
630
|
example: "{{ { id: $json.id, name: $json.first + ' ' + $json.last } }}",
|
|
589
|
-
|
|
631
|
+
description: "Used when the mode above is set to one expression."
|
|
590
632
|
}
|
|
591
633
|
]
|
|
592
634
|
},
|
|
@@ -636,7 +678,15 @@ var KINDS = [
|
|
|
636
678
|
},
|
|
637
679
|
{ type: "text", key: "table", label: "Table / collection", required: true },
|
|
638
680
|
{ type: "text", key: "key", label: "Key" },
|
|
639
|
-
{
|
|
681
|
+
{
|
|
682
|
+
type: "keyvalue",
|
|
683
|
+
key: "where",
|
|
684
|
+
label: "Where",
|
|
685
|
+
description: "Field/value pairs to match. For query and list operations.",
|
|
686
|
+
keyLabel: "Field",
|
|
687
|
+
valueLabel: "Equals",
|
|
688
|
+
addLabel: "Add filter"
|
|
689
|
+
},
|
|
640
690
|
{ type: "expression", key: "value", label: "Value (set only)", example: "{{ $json }}" },
|
|
641
691
|
{ type: "credential", key: "store", label: "Data store", credentialType: "data_store" }
|
|
642
692
|
]
|
|
@@ -678,13 +728,32 @@ var KINDS = [
|
|
|
678
728
|
{ type: "expression", key: "prompt", label: "User prompt", example: "{{ $json.question }}", required: true },
|
|
679
729
|
{ type: "number", key: "temperature", label: "Temperature", min: 0, max: 2, step: 0.1, default: 0.7 },
|
|
680
730
|
{ type: "number", key: "max_tokens", label: "Max tokens", min: 1, max: 8192, default: 1024 },
|
|
681
|
-
{
|
|
731
|
+
{
|
|
732
|
+
type: "repeater",
|
|
733
|
+
key: "tools",
|
|
734
|
+
label: "Tools",
|
|
735
|
+
description: "Tools the model may call.",
|
|
736
|
+
titleKey: "name",
|
|
737
|
+
addLabel: "Add tool",
|
|
738
|
+
fields: [
|
|
739
|
+
{ type: "text", key: "name", label: "Name", required: true, placeholder: "search_index" },
|
|
740
|
+
{ type: "text", key: "description", label: "When to use it" },
|
|
741
|
+
{
|
|
742
|
+
type: "json",
|
|
743
|
+
key: "input_schema",
|
|
744
|
+
label: "Input schema",
|
|
745
|
+
description: "JSON Schema for the tool's arguments."
|
|
746
|
+
}
|
|
747
|
+
]
|
|
748
|
+
},
|
|
682
749
|
{ type: "credential", key: "credential", label: "API credential", credentialType: "llm_credential" }
|
|
683
750
|
]
|
|
684
751
|
},
|
|
685
752
|
{
|
|
686
|
-
name: "@particle-academy/
|
|
687
|
-
|
|
753
|
+
name: "@particle-academy/llm_router",
|
|
754
|
+
// Every id this node has ever shipped under keeps resolving — MOIC's saved
|
|
755
|
+
// flows carry the bare `llm_branch`.
|
|
756
|
+
aliases: ["llm_router", "llm_branch", "@fancy/llm_branch", "@fancy/llm_router"],
|
|
688
757
|
category: "ai",
|
|
689
758
|
label: "LLM Router",
|
|
690
759
|
description: "Let a model choose which route the flow takes.",
|
|
@@ -696,7 +765,7 @@ var KINDS = [
|
|
|
696
765
|
// A shuttle, not an engine: it carries the routes out to whatever LLM
|
|
697
766
|
// client the host registered and carries the choice back. No provider SDK
|
|
698
767
|
// reaches core, so this stays a builtin without adding a dependency.
|
|
699
|
-
executor:
|
|
768
|
+
executor: llmRouterExecutor,
|
|
700
769
|
configSchema: [
|
|
701
770
|
{
|
|
702
771
|
type: "textarea",
|
|
@@ -793,7 +862,17 @@ var KINDS = [
|
|
|
793
862
|
configSchema: [
|
|
794
863
|
...HTTP_METHODS,
|
|
795
864
|
{ type: "text", key: "url", label: "URL", placeholder: "https://api.example.com/...", required: true },
|
|
796
|
-
{
|
|
865
|
+
{
|
|
866
|
+
type: "keyvalue",
|
|
867
|
+
key: "headers",
|
|
868
|
+
label: "Headers",
|
|
869
|
+
keyLabel: "Header",
|
|
870
|
+
valueLabel: "Value",
|
|
871
|
+
keyPlaceholder: "content-type",
|
|
872
|
+
valuePlaceholder: "application/json",
|
|
873
|
+
addLabel: "Add header",
|
|
874
|
+
default: { "content-type": "application/json" }
|
|
875
|
+
},
|
|
797
876
|
{ type: "json", key: "body", label: "Body" },
|
|
798
877
|
{ type: "credential", key: "auth", label: "Auth", credentialType: "api_credential" }
|
|
799
878
|
]
|
|
@@ -807,7 +886,14 @@ var KINDS = [
|
|
|
807
886
|
icon: "\u2197",
|
|
808
887
|
configSchema: [
|
|
809
888
|
{ type: "text", key: "url", label: "URL", required: true },
|
|
810
|
-
{
|
|
889
|
+
{
|
|
890
|
+
type: "keyvalue",
|
|
891
|
+
key: "headers",
|
|
892
|
+
label: "Headers",
|
|
893
|
+
keyLabel: "Header",
|
|
894
|
+
valueLabel: "Value",
|
|
895
|
+
addLabel: "Add header"
|
|
896
|
+
},
|
|
811
897
|
{ type: "expression", key: "payload", label: "Payload", required: true, example: "{{ $json }}" }
|
|
812
898
|
]
|
|
813
899
|
},
|
|
@@ -897,6 +983,6 @@ function buildNodeTypes() {
|
|
|
897
983
|
return map;
|
|
898
984
|
}
|
|
899
985
|
|
|
900
|
-
export { BUILTIN_KINDS, DEFAULT_MAX_DEPTH, RegistryNode, buildNodeTypes,
|
|
901
|
-
//# sourceMappingURL=chunk-
|
|
902
|
-
//# sourceMappingURL=chunk-
|
|
986
|
+
export { BUILTIN_KINDS, DEFAULT_MAX_DEPTH, RegistryNode, buildNodeTypes, declaredRoutes, llmRouterExecutor, registerBuiltinKinds, resolveFallbackPort, subflowExecutor, subflowMode, subflowPorts };
|
|
987
|
+
//# sourceMappingURL=chunk-7U3EP4Q5.js.map
|
|
988
|
+
//# sourceMappingURL=chunk-7U3EP4Q5.js.map
|