@foresthubai/workflow-core 0.4.7 → 0.4.8
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/deploy/requirements.d.ts +1 -1
- package/dist/deploy/requirements.d.ts.map +1 -1
- package/dist/deploy/requirements.js +22 -6
- package/dist/deploy/requirements.js.map +1 -1
- package/dist/node/AINode.d.ts +31 -0
- package/dist/node/AINode.d.ts.map +1 -0
- package/dist/node/AINode.js +85 -0
- package/dist/node/AINode.js.map +1 -0
- package/dist/node/Node.d.ts +3 -4
- package/dist/node/Node.d.ts.map +1 -1
- package/dist/node/NodeRegistry.d.ts.map +1 -1
- package/dist/node/NodeRegistry.js +1 -2
- package/dist/node/NodeRegistry.js.map +1 -1
- package/package.json +1 -1
- package/src/deploy/requirements.test.ts +4 -3
- package/src/deploy/requirements.ts +32 -14
- package/src/diagnostics/diagnostics.test.ts +1 -1
- package/src/node/{AgentNode.ts → AINode.ts} +124 -85
- package/src/node/Node.ts +3 -5
- package/src/node/NodeRegistry.ts +1 -2
- package/src/node/MLInferenceNode.ts +0 -46
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Workflow } from "../workflow";
|
|
2
|
-
export type BindingKind = "hardware" | "mqtt" | "camera" | "declaredModel" | "catalogModel";
|
|
2
|
+
export type BindingKind = "hardware" | "mqtt" | "camera" | "declaredModel" | "mlInference" | "catalogModel";
|
|
3
3
|
export declare function workflowBindingRequirements(workflow: Workflow): Record<string, BindingKind>;
|
|
4
4
|
/**
|
|
5
5
|
* Model ids that Agent nodes reference but the workflow does not declare in
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"requirements.d.ts","sourceRoot":"","sources":["../../src/deploy/requirements.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAiB5C,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,eAAe,GAAG,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"requirements.d.ts","sourceRoot":"","sources":["../../src/deploy/requirements.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAiB5C,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,eAAe,GAAG,aAAa,GAAG,cAAc,CAAC;AA0B5G,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAmD3F;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,EAAE,CAazE"}
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
// Copyright (c) 2026 ForestHub.
|
|
3
3
|
// Drift sentinel: a new ChannelType breaks compilation here until it is
|
|
4
|
-
// classified in workflowBindingRequirements' switch.
|
|
4
|
+
// classified in workflowBindingRequirements' channel switch.
|
|
5
5
|
function assertNeverChannel(t) {
|
|
6
6
|
throw new Error(`unhandled channel type: ${String(t)}`);
|
|
7
7
|
}
|
|
8
|
+
// Drift sentinel: a new ModelType breaks compilation here until it is classified
|
|
9
|
+
// in workflowBindingRequirements' model switch.
|
|
10
|
+
function assertNeverModel(t) {
|
|
11
|
+
throw new Error(`unhandled model type: ${String(t)}`);
|
|
12
|
+
}
|
|
8
13
|
// workflowBindingRequirements returns the resources a deploy must bind, keyed by
|
|
9
14
|
// workflow logical id — the binding surface. The TS twin of the backend's
|
|
10
15
|
// deploy.WorkflowBindingRequirements: both must derive the SAME id->kind map from
|
|
@@ -42,11 +47,22 @@ export function workflowBindingRequirements(workflow) {
|
|
|
42
47
|
return assertNeverChannel(channel.type);
|
|
43
48
|
}
|
|
44
49
|
}
|
|
45
|
-
// Every declared model needs a source binding,
|
|
46
|
-
//
|
|
47
|
-
// Mirrors the backend
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
// Every declared model needs a source binding, but of a different kind by family:
|
|
51
|
+
// an LLMModel binds a model source ("declaredModel"); an MLModel is served by an
|
|
52
|
+
// ml-inference component ("mlInference"). Mirrors the backend's workflowModelIDs
|
|
53
|
+
// split — both sides must agree on which kind each declared model gets.
|
|
54
|
+
for (const model of Object.values(workflow.models)) {
|
|
55
|
+
switch (model.type) {
|
|
56
|
+
case "LLMModel":
|
|
57
|
+
reqs[model.id] = "declaredModel";
|
|
58
|
+
break;
|
|
59
|
+
case "MLModel":
|
|
60
|
+
reqs[model.id] = "mlInference";
|
|
61
|
+
break;
|
|
62
|
+
default:
|
|
63
|
+
return assertNeverModel(model.type);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
50
66
|
// Catalog models: referenced by an Agent node but not declared. Keyed by model
|
|
51
67
|
// id (canonical, matching the backend surface) — not collapsed to providers
|
|
52
68
|
// here. getReferencedCatalogModelIds already excludes declared ids, so this
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"requirements.js","sourceRoot":"","sources":["../../src/deploy/requirements.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,gCAAgC;AA0BhC,wEAAwE;AACxE,
|
|
1
|
+
{"version":3,"file":"requirements.js","sourceRoot":"","sources":["../../src/deploy/requirements.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { NodeBase } from "./Node";
|
|
2
|
+
import type { Reference, Schemas } from "../api";
|
|
3
|
+
import { OutputBinding, OutputDeclaration } from "../parameter";
|
|
4
|
+
import { NodeDefinition } from "./NodeDefinition";
|
|
5
|
+
export type MemoryRef = Schemas["MemoryRef"];
|
|
6
|
+
export interface AgentNode extends NodeBase {
|
|
7
|
+
type: "Agent";
|
|
8
|
+
arguments: {
|
|
9
|
+
name: string;
|
|
10
|
+
model: string;
|
|
11
|
+
instructions: string;
|
|
12
|
+
maxTurns: number | undefined;
|
|
13
|
+
outputDeclarations: OutputDeclaration[];
|
|
14
|
+
memoryRefs: MemoryRef[];
|
|
15
|
+
answer: OutputBinding;
|
|
16
|
+
toolDescription?: string;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export interface MLInferenceNode extends NodeBase {
|
|
20
|
+
type: "MLInference";
|
|
21
|
+
arguments: {
|
|
22
|
+
model: string;
|
|
23
|
+
input: Reference | undefined;
|
|
24
|
+
output: OutputBinding;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export type AINodeType = "Agent" | "MLInference";
|
|
28
|
+
export type AINode = AgentNode | MLInferenceNode;
|
|
29
|
+
export declare const AgentNodeDefinition: NodeDefinition;
|
|
30
|
+
export declare const MLInferenceNodeDefinition: NodeDefinition;
|
|
31
|
+
//# sourceMappingURL=AINode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AINode.d.ts","sourceRoot":"","sources":["../../src/node/AINode.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAClC,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEhE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,MAAM,MAAM,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;AAE7C,MAAM,WAAW,SAAU,SAAQ,QAAQ;IACzC,IAAI,EAAE,OAAO,CAAC;IACd,SAAS,EAAE;QACT,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,YAAY,EAAE,MAAM,CAAC;QACrB,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;QAC7B,kBAAkB,EAAE,iBAAiB,EAAE,CAAC;QACxC,UAAU,EAAE,SAAS,EAAE,CAAC;QACxB,MAAM,EAAE,aAAa,CAAC;QACtB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;CACH;AAMD,MAAM,WAAW,eAAgB,SAAQ,QAAQ;IAC/C,IAAI,EAAE,aAAa,CAAC;IACpB,SAAS,EAAE;QACT,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,SAAS,GAAG,SAAS,CAAC;QAC7B,MAAM,EAAE,aAAa,CAAC;KACvB,CAAC;CACH;AAED,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,aAAa,CAAC;AACjD,MAAM,MAAM,MAAM,GAAG,SAAS,GAAG,eAAe,CAAC;AAIjD,eAAO,MAAM,mBAAmB,EAAE,cAyDjC,CAAC;AAEF,eAAO,MAAM,yBAAyB,EAAE,cAqBvC,CAAC"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (c) 2026 ForestHub.
|
|
3
|
+
import { NodeCategory } from "./constants";
|
|
4
|
+
// Node Definitions
|
|
5
|
+
export const AgentNodeDefinition = {
|
|
6
|
+
type: "Agent",
|
|
7
|
+
label: "LLM Agent",
|
|
8
|
+
category: NodeCategory.AI,
|
|
9
|
+
description: "AI-powered agent for intelligent processing",
|
|
10
|
+
canBranch: true, // Control output may fan out to multiple branches (tool output is always multi-target).
|
|
11
|
+
outputs: [
|
|
12
|
+
{ id: "answer", label: "Answer", type: "static", dataType: "string" },
|
|
13
|
+
{ id: "outputDeclarations", label: "Structured Output", type: "list" },
|
|
14
|
+
],
|
|
15
|
+
parameters: [
|
|
16
|
+
{
|
|
17
|
+
id: "name",
|
|
18
|
+
label: "Name",
|
|
19
|
+
description: "Name of the agent",
|
|
20
|
+
optional: true,
|
|
21
|
+
type: "string",
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
id: "model",
|
|
25
|
+
label: "Model",
|
|
26
|
+
description: "AI model to use for the agent",
|
|
27
|
+
type: "modelSelect",
|
|
28
|
+
modelType: ["LLMModel"],
|
|
29
|
+
capabilities: ["chat"],
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
id: "instructions",
|
|
33
|
+
label: "Instructions",
|
|
34
|
+
description: "Instructions for the cloud agent that act as system prompt",
|
|
35
|
+
type: "string",
|
|
36
|
+
multiline: true,
|
|
37
|
+
optional: true,
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
id: "maxTurns",
|
|
41
|
+
label: "Max Turns",
|
|
42
|
+
description: "Maximum number of agent runner turns",
|
|
43
|
+
type: "int",
|
|
44
|
+
optional: true,
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
id: "memoryRefs",
|
|
48
|
+
label: "Memory Files",
|
|
49
|
+
description: "Project memory files this agent can access, with per-file read or read+write mode",
|
|
50
|
+
type: "memory-refs",
|
|
51
|
+
default: [],
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
id: "toolDescription",
|
|
55
|
+
label: "Tool Description",
|
|
56
|
+
description: "Description shown to the calling agent when this agent is wired as a tool",
|
|
57
|
+
type: "string",
|
|
58
|
+
multiline: true,
|
|
59
|
+
activationRules: [{ type: "isToolInput" }],
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
};
|
|
63
|
+
export const MLInferenceNodeDefinition = {
|
|
64
|
+
type: "MLInference",
|
|
65
|
+
label: "ML Inference",
|
|
66
|
+
category: NodeCategory.AI,
|
|
67
|
+
description: "Runs a machine-learning model on an input and returns its result",
|
|
68
|
+
outputs: [{ id: "output", label: "Result", type: "static", dataType: "string" }],
|
|
69
|
+
parameters: [
|
|
70
|
+
{
|
|
71
|
+
id: "model",
|
|
72
|
+
label: "Model",
|
|
73
|
+
description: "ML model to run",
|
|
74
|
+
type: "modelSelect",
|
|
75
|
+
modelType: ["MLModel"],
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
id: "input",
|
|
79
|
+
label: "Input",
|
|
80
|
+
description: "Variable whose value is fed to the model",
|
|
81
|
+
type: "variableSelect",
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
};
|
|
85
|
+
//# sourceMappingURL=AINode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AINode.js","sourceRoot":"","sources":["../../src/node/AINode.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,gCAAgC;AAKhC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAmC3C,mBAAmB;AAEnB,MAAM,CAAC,MAAM,mBAAmB,GAAmB;IACjD,IAAI,EAAE,OAAO;IACb,KAAK,EAAE,WAAW;IAClB,QAAQ,EAAE,YAAY,CAAC,EAAE;IACzB,WAAW,EAAE,6CAA6C;IAC1D,SAAS,EAAE,IAAI,EAAE,wFAAwF;IACzG,OAAO,EAAE;QACP,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE;QACrE,EAAE,EAAE,EAAE,oBAAoB,EAAE,KAAK,EAAE,mBAAmB,EAAE,IAAI,EAAE,MAAM,EAAE;KACvE;IACD,UAAU,EAAE;QACV;YACE,EAAE,EAAE,MAAM;YACV,KAAK,EAAE,MAAM;YACb,WAAW,EAAE,mBAAmB;YAChC,QAAQ,EAAE,IAAI;YACd,IAAI,EAAE,QAAQ;SACf;QACD;YACE,EAAE,EAAE,OAAO;YACX,KAAK,EAAE,OAAO;YACd,WAAW,EAAE,+BAA+B;YAC5C,IAAI,EAAE,aAAa;YACnB,SAAS,EAAE,CAAC,UAAU,CAAC;YACvB,YAAY,EAAE,CAAC,MAAM,CAAC;SACvB;QACD;YACE,EAAE,EAAE,cAAc;YAClB,KAAK,EAAE,cAAc;YACrB,WAAW,EAAE,4DAA4D;YACzE,IAAI,EAAE,QAAQ;YACd,SAAS,EAAE,IAAI;YACf,QAAQ,EAAE,IAAI;SACf;QACD;YACE,EAAE,EAAE,UAAU;YACd,KAAK,EAAE,WAAW;YAClB,WAAW,EAAE,sCAAsC;YACnD,IAAI,EAAE,KAAK;YACX,QAAQ,EAAE,IAAI;SACf;QACD;YACE,EAAE,EAAE,YAAY;YAChB,KAAK,EAAE,cAAc;YACrB,WAAW,EAAE,mFAAmF;YAChG,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE,EAAE;SACZ;QACD;YACE,EAAE,EAAE,iBAAiB;YACrB,KAAK,EAAE,kBAAkB;YACzB,WAAW,EAAE,2EAA2E;YACxF,IAAI,EAAE,QAAQ;YACd,SAAS,EAAE,IAAI;YACf,eAAe,EAAE,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;SAC3C;KACF;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,yBAAyB,GAAmB;IACvD,IAAI,EAAE,aAAa;IACnB,KAAK,EAAE,cAAc;IACrB,QAAQ,EAAE,YAAY,CAAC,EAAE;IACzB,WAAW,EAAE,kEAAkE;IAC/E,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;IAChF,UAAU,EAAE;QACV;YACE,EAAE,EAAE,OAAO;YACX,KAAK,EAAE,OAAO;YACd,WAAW,EAAE,iBAAiB;YAC9B,IAAI,EAAE,aAAa;YACnB,SAAS,EAAE,CAAC,SAAS,CAAC;SACvB;QACD;YACE,EAAE,EAAE,OAAO;YACX,KAAK,EAAE,OAAO;YACd,WAAW,EAAE,0CAA0C;YACvD,IAAI,EAAE,gBAAgB;SACvB;KACF;CACF,CAAC"}
|
package/dist/node/Node.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import type { DataType } from "../api";
|
|
2
2
|
import { InputNode, InputNodeType } from "./InputNode";
|
|
3
3
|
import { OutputNode, OutputNodeType } from "./OutputNode";
|
|
4
|
-
import {
|
|
5
|
-
import { MLInferenceNode, MLInferenceNodeType } from "./MLInferenceNode";
|
|
4
|
+
import { AINode, AINodeType } from "./AINode";
|
|
6
5
|
import { LogicNode, LogicNodeType } from "./LogicNode";
|
|
7
6
|
import { DataNode, DataNodeType } from "./DataNode";
|
|
8
7
|
import { TriggerNode, TriggerNodeType } from "./TriggerNode";
|
|
@@ -13,13 +12,13 @@ export type NodeOutput = {
|
|
|
13
12
|
name: string;
|
|
14
13
|
dataType: DataType;
|
|
15
14
|
};
|
|
16
|
-
export type NodeType = InputNodeType | OutputNodeType |
|
|
15
|
+
export type NodeType = InputNodeType | OutputNodeType | AINodeType | LogicNodeType | DataNodeType | TriggerNodeType | ToolNodeType | FunctionCallNodeType | MqttNodeType;
|
|
17
16
|
/**
|
|
18
17
|
* NodeData represents the runtime data for a node in the workflow builder.
|
|
19
18
|
* It is a union type of all specific node types, each with their own typed parameters.
|
|
20
19
|
* Use this type when you need strong typing for a specific node.
|
|
21
20
|
*/
|
|
22
|
-
export type NodeData = InputNode | OutputNode |
|
|
21
|
+
export type NodeData = InputNode | OutputNode | AINode | LogicNode | DataNode | TriggerNode | ToolNode | FunctionCallNode | MqttNode;
|
|
23
22
|
/**
|
|
24
23
|
* Full domain node entity held on a {@link Canvas}: the {@link NodeData}
|
|
25
24
|
* payload plus its canvas layout position, flattened. id/type/arguments/label
|
package/dist/node/Node.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Node.d.ts","sourceRoot":"","sources":["../../src/node/Node.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"Node.d.ts","sourceRoot":"","sources":["../../src/node/Node.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACxE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAEpD,MAAM,MAAM,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,CAAC;AAC9D,MAAM,MAAM,QAAQ,GAChB,aAAa,GACb,cAAc,GACd,UAAU,GACV,aAAa,GACb,YAAY,GACZ,eAAe,GACf,YAAY,GACZ,oBAAoB,GACpB,YAAY,CAAC;AAEjB;;;;GAIG;AACH,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,GAAG,gBAAgB,GAAG,QAAQ,CAAC;AAErI;;;;;GAKG;AACH,MAAM,MAAM,IAAI,GAAG,QAAQ,GAAG;IAAE,QAAQ,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC;AAErE;;;;;;;;;GASG;AACH,MAAM,WAAW,QAAS,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACvD,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NodeRegistry.d.ts","sourceRoot":"","sources":["../../src/node/NodeRegistry.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"NodeRegistry.d.ts","sourceRoot":"","sources":["../../src/node/NodeRegistry.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAK3C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD;;GAEG;AACH,cAAM,sBAAsB;IAC1B,OAAO,CAAC,KAAK,CAA4C;IACzD,OAAO,CAAC,WAAW,CAAS;IAE5B,UAAU;IAkCV,OAAO,CAAC,QAAQ;IAIhB,MAAM,IAAI,cAAc,EAAE;IAI1B,gBAAgB,IAAI,YAAY,EAAE;IAKlC,SAAS,CAAC,IAAI,EAAE,QAAQ,GAAG,cAAc,GAAG,SAAS;IAIrD,aAAa,CAAC,QAAQ,EAAE,YAAY,GAAG,cAAc,EAAE;CAGxD;AAGD,eAAO,MAAM,YAAY,wBAA+B,CAAC"}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
// Copyright (c) 2026 ForestHub.
|
|
3
3
|
import { ReadPinNodeDefinition, SerialReadNodeDefinition, RetrieverNodeDefinition, WebFetchNodeDefinition, CameraCaptureNodeDefinition } from "./InputNode";
|
|
4
|
-
import { AgentNodeDefinition } from "./
|
|
5
|
-
import { MLInferenceNodeDefinition } from "./MLInferenceNode";
|
|
4
|
+
import { AgentNodeDefinition, MLInferenceNodeDefinition } from "./AINode";
|
|
6
5
|
import { DelayNodeDefinition, TickerNodeDefinition, AlarmNodeDefinition, OnFunctionCallNodeDefinition, OnStartupNodeDefinition, OnPinEdgeNodeDefinition, OnSerialReceiveNodeDefinition, OnThresholdNodeDefinition, } from "./TriggerNode";
|
|
7
6
|
import { WebSearchToolNodeDefinition } from "./ToolNode";
|
|
8
7
|
import { SerialWriteNodeDefinition, WritePinNodeDefinition } from "./OutputNode";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NodeRegistry.js","sourceRoot":"","sources":["../../src/node/NodeRegistry.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,gCAAgC;AAEhC,OAAO,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAC;AAC5J,OAAO,EAAE,mBAAmB,EAAE,
|
|
1
|
+
{"version":3,"file":"NodeRegistry.js","sourceRoot":"","sources":["../../src/node/NodeRegistry.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -94,9 +94,9 @@ describe("workflowBindingRequirements", () => {
|
|
|
94
94
|
expect(workflowBindingRequirements(workflow({ channels: chs }))).toEqual({ led: "hardware" });
|
|
95
95
|
});
|
|
96
96
|
|
|
97
|
-
it("
|
|
97
|
+
it("splits declared models: LLMModel -> 'declaredModel', MLModel -> 'mlInference'", () => {
|
|
98
98
|
const models = modelsById([llm("local-llm"), ml("yolo")]);
|
|
99
|
-
expect(workflowBindingRequirements(workflow({ models }))).toEqual({ "local-llm": "declaredModel", yolo: "
|
|
99
|
+
expect(workflowBindingRequirements(workflow({ models }))).toEqual({ "local-llm": "declaredModel", yolo: "mlInference" });
|
|
100
100
|
});
|
|
101
101
|
|
|
102
102
|
it("maps a referenced-but-undeclared catalog model to 'catalogModel', keyed by model id", () => {
|
|
@@ -119,7 +119,7 @@ describe("workflowBindingRequirements", () => {
|
|
|
119
119
|
it("produces the full surface for a mixed workflow", () => {
|
|
120
120
|
const wf = workflow({
|
|
121
121
|
channels: byId([channel("led", "GPIOOUT"), channel("telemetry", "MQTT"), channel("cam0", "CAMERA"), channel("log", "LOG")]),
|
|
122
|
-
models: modelsById([llm("local-llm")]),
|
|
122
|
+
models: modelsById([llm("local-llm"), ml("yolo")]),
|
|
123
123
|
nodes: [agent("a1", "claude-sonnet")],
|
|
124
124
|
});
|
|
125
125
|
const expected: Record<string, BindingKind> = {
|
|
@@ -127,6 +127,7 @@ describe("workflowBindingRequirements", () => {
|
|
|
127
127
|
telemetry: "mqtt",
|
|
128
128
|
cam0: "camera",
|
|
129
129
|
"local-llm": "declaredModel",
|
|
130
|
+
yolo: "mlInference",
|
|
130
131
|
"claude-sonnet": "catalogModel",
|
|
131
132
|
};
|
|
132
133
|
expect(workflowBindingRequirements(wf)).toEqual(expected);
|
|
@@ -14,23 +14,29 @@ import type { Workflow } from "../workflow";
|
|
|
14
14
|
// CROSS-LANGUAGE SEAM: these string values MUST match the backend's
|
|
15
15
|
// deploy.BindingRequirement constants (fh-backend deploy.WorkflowBindingRequirements),
|
|
16
16
|
// which are themselves the ResourceBindingRequest discriminators
|
|
17
|
-
// ("hardware"/"mqtt"/"declaredModel"/"catalogModel"/"rag").
|
|
18
|
-
// here silently disagrees with the backend about what a
|
|
17
|
+
// ("hardware"/"mqtt"/"camera"/"declaredModel"/"mlInference"/"catalogModel"/"rag").
|
|
18
|
+
// A value that drifts here silently disagrees with the backend about what a
|
|
19
|
+
// workflow needs bound.
|
|
19
20
|
//
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
//
|
|
24
|
-
//
|
|
25
|
-
|
|
26
|
-
export type BindingKind = "hardware" | "mqtt" | "camera" | "declaredModel" | "catalogModel";
|
|
21
|
+
// One deliberate asymmetry with the backend today: "rag" is absent. OSS is behind
|
|
22
|
+
// on retrieval — it does not yet extract a VectorDatabase memory resource as a
|
|
23
|
+
// requirement (the backend emits "rag"). A standalone engine has no retriever, so
|
|
24
|
+
// such a workflow is refused at deploy; add "rag" here when the OSS engine gains a
|
|
25
|
+
// retrieval backing.
|
|
26
|
+
export type BindingKind = "hardware" | "mqtt" | "camera" | "declaredModel" | "mlInference" | "catalogModel";
|
|
27
27
|
|
|
28
28
|
// Drift sentinel: a new ChannelType breaks compilation here until it is
|
|
29
|
-
// classified in workflowBindingRequirements' switch.
|
|
29
|
+
// classified in workflowBindingRequirements' channel switch.
|
|
30
30
|
function assertNeverChannel(t: never): never {
|
|
31
31
|
throw new Error(`unhandled channel type: ${String(t)}`);
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
// Drift sentinel: a new ModelType breaks compilation here until it is classified
|
|
35
|
+
// in workflowBindingRequirements' model switch.
|
|
36
|
+
function assertNeverModel(t: never): never {
|
|
37
|
+
throw new Error(`unhandled model type: ${String(t)}`);
|
|
38
|
+
}
|
|
39
|
+
|
|
34
40
|
// workflowBindingRequirements returns the resources a deploy must bind, keyed by
|
|
35
41
|
// workflow logical id — the binding surface. The TS twin of the backend's
|
|
36
42
|
// deploy.WorkflowBindingRequirements: both must derive the SAME id->kind map from
|
|
@@ -70,10 +76,22 @@ export function workflowBindingRequirements(workflow: Workflow): Record<string,
|
|
|
70
76
|
}
|
|
71
77
|
}
|
|
72
78
|
|
|
73
|
-
// Every declared model needs a source binding,
|
|
74
|
-
//
|
|
75
|
-
// Mirrors the backend
|
|
76
|
-
|
|
79
|
+
// Every declared model needs a source binding, but of a different kind by family:
|
|
80
|
+
// an LLMModel binds a model source ("declaredModel"); an MLModel is served by an
|
|
81
|
+
// ml-inference component ("mlInference"). Mirrors the backend's workflowModelIDs
|
|
82
|
+
// split — both sides must agree on which kind each declared model gets.
|
|
83
|
+
for (const model of Object.values(workflow.models)) {
|
|
84
|
+
switch (model.type) {
|
|
85
|
+
case "LLMModel":
|
|
86
|
+
reqs[model.id] = "declaredModel";
|
|
87
|
+
break;
|
|
88
|
+
case "MLModel":
|
|
89
|
+
reqs[model.id] = "mlInference";
|
|
90
|
+
break;
|
|
91
|
+
default:
|
|
92
|
+
return assertNeverModel(model.type);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
77
95
|
|
|
78
96
|
// Catalog models: referenced by an Agent node but not declared. Keyed by model
|
|
79
97
|
// id (canonical, matching the backend surface) — not collapsed to providers
|
|
@@ -8,7 +8,7 @@ import type { FunctionDeclaration } from "../function";
|
|
|
8
8
|
import { NodeCategory } from "../node";
|
|
9
9
|
import { SetVariableNodeDefinition } from "../node/DataNode";
|
|
10
10
|
import { RetrieverNodeDefinition } from "../node/InputNode";
|
|
11
|
-
import { AgentNodeDefinition } from "../node/
|
|
11
|
+
import { AgentNodeDefinition } from "../node/AINode";
|
|
12
12
|
import { OnThresholdNodeDefinition } from "../node/TriggerNode";
|
|
13
13
|
import { WebSearchToolNodeDefinition } from "../node/ToolNode";
|
|
14
14
|
import {
|
|
@@ -1,85 +1,124 @@
|
|
|
1
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
-
// Copyright (c) 2026 ForestHub.
|
|
3
|
-
|
|
4
|
-
import { NodeBase } from "./Node";
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
7
|
-
import { NodeCategory } from "./constants";
|
|
8
|
-
import { NodeDefinition } from "./NodeDefinition";
|
|
9
|
-
|
|
10
|
-
export type MemoryRef = Schemas["MemoryRef"];
|
|
11
|
-
|
|
12
|
-
export interface AgentNode extends NodeBase {
|
|
13
|
-
type: "Agent";
|
|
14
|
-
arguments: {
|
|
15
|
-
name: string;
|
|
16
|
-
model: string;
|
|
17
|
-
instructions: string;
|
|
18
|
-
maxTurns: number | undefined;
|
|
19
|
-
outputDeclarations: OutputDeclaration[];
|
|
20
|
-
memoryRefs: MemoryRef[];
|
|
21
|
-
answer: OutputBinding;
|
|
22
|
-
toolDescription?: string;
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
id: "
|
|
64
|
-
label: "
|
|
65
|
-
description: "
|
|
66
|
-
type: "
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (c) 2026 ForestHub.
|
|
3
|
+
|
|
4
|
+
import { NodeBase } from "./Node";
|
|
5
|
+
import type { Reference, Schemas } from "../api";
|
|
6
|
+
import { OutputBinding, OutputDeclaration } from "../parameter";
|
|
7
|
+
import { NodeCategory } from "./constants";
|
|
8
|
+
import { NodeDefinition } from "./NodeDefinition";
|
|
9
|
+
|
|
10
|
+
export type MemoryRef = Schemas["MemoryRef"];
|
|
11
|
+
|
|
12
|
+
export interface AgentNode extends NodeBase {
|
|
13
|
+
type: "Agent";
|
|
14
|
+
arguments: {
|
|
15
|
+
name: string;
|
|
16
|
+
model: string;
|
|
17
|
+
instructions: string;
|
|
18
|
+
maxTurns: number | undefined;
|
|
19
|
+
outputDeclarations: OutputDeclaration[];
|
|
20
|
+
memoryRefs: MemoryRef[];
|
|
21
|
+
answer: OutputBinding;
|
|
22
|
+
toolDescription?: string;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// MLInference — runs a declared ML model on an input and returns its result.
|
|
27
|
+
// The model is selected from the workflow's declared MLModels; the input is a
|
|
28
|
+
// reference to a variable whose value is fed to the model, and the result is
|
|
29
|
+
// emitted as a string.
|
|
30
|
+
export interface MLInferenceNode extends NodeBase {
|
|
31
|
+
type: "MLInference";
|
|
32
|
+
arguments: {
|
|
33
|
+
model: string;
|
|
34
|
+
input: Reference | undefined;
|
|
35
|
+
output: OutputBinding;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export type AINodeType = "Agent" | "MLInference";
|
|
40
|
+
export type AINode = AgentNode | MLInferenceNode;
|
|
41
|
+
|
|
42
|
+
// Node Definitions
|
|
43
|
+
|
|
44
|
+
export const AgentNodeDefinition: NodeDefinition = {
|
|
45
|
+
type: "Agent",
|
|
46
|
+
label: "LLM Agent",
|
|
47
|
+
category: NodeCategory.AI,
|
|
48
|
+
description: "AI-powered agent for intelligent processing",
|
|
49
|
+
canBranch: true, // Control output may fan out to multiple branches (tool output is always multi-target).
|
|
50
|
+
outputs: [
|
|
51
|
+
{ id: "answer", label: "Answer", type: "static", dataType: "string" },
|
|
52
|
+
{ id: "outputDeclarations", label: "Structured Output", type: "list" },
|
|
53
|
+
],
|
|
54
|
+
parameters: [
|
|
55
|
+
{
|
|
56
|
+
id: "name",
|
|
57
|
+
label: "Name",
|
|
58
|
+
description: "Name of the agent",
|
|
59
|
+
optional: true,
|
|
60
|
+
type: "string",
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
id: "model",
|
|
64
|
+
label: "Model",
|
|
65
|
+
description: "AI model to use for the agent",
|
|
66
|
+
type: "modelSelect",
|
|
67
|
+
modelType: ["LLMModel"],
|
|
68
|
+
capabilities: ["chat"],
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
id: "instructions",
|
|
72
|
+
label: "Instructions",
|
|
73
|
+
description: "Instructions for the cloud agent that act as system prompt",
|
|
74
|
+
type: "string",
|
|
75
|
+
multiline: true,
|
|
76
|
+
optional: true,
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
id: "maxTurns",
|
|
80
|
+
label: "Max Turns",
|
|
81
|
+
description: "Maximum number of agent runner turns",
|
|
82
|
+
type: "int",
|
|
83
|
+
optional: true,
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
id: "memoryRefs",
|
|
87
|
+
label: "Memory Files",
|
|
88
|
+
description: "Project memory files this agent can access, with per-file read or read+write mode",
|
|
89
|
+
type: "memory-refs",
|
|
90
|
+
default: [],
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
id: "toolDescription",
|
|
94
|
+
label: "Tool Description",
|
|
95
|
+
description: "Description shown to the calling agent when this agent is wired as a tool",
|
|
96
|
+
type: "string",
|
|
97
|
+
multiline: true,
|
|
98
|
+
activationRules: [{ type: "isToolInput" }],
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export const MLInferenceNodeDefinition: NodeDefinition = {
|
|
104
|
+
type: "MLInference",
|
|
105
|
+
label: "ML Inference",
|
|
106
|
+
category: NodeCategory.AI,
|
|
107
|
+
description: "Runs a machine-learning model on an input and returns its result",
|
|
108
|
+
outputs: [{ id: "output", label: "Result", type: "static", dataType: "string" }],
|
|
109
|
+
parameters: [
|
|
110
|
+
{
|
|
111
|
+
id: "model",
|
|
112
|
+
label: "Model",
|
|
113
|
+
description: "ML model to run",
|
|
114
|
+
type: "modelSelect",
|
|
115
|
+
modelType: ["MLModel"],
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
id: "input",
|
|
119
|
+
label: "Input",
|
|
120
|
+
description: "Variable whose value is fed to the model",
|
|
121
|
+
type: "variableSelect",
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
};
|
package/src/node/Node.ts
CHANGED
|
@@ -12,8 +12,7 @@
|
|
|
12
12
|
import type { DataType } from "../api";
|
|
13
13
|
import { InputNode, InputNodeType } from "./InputNode";
|
|
14
14
|
import { OutputNode, OutputNodeType } from "./OutputNode";
|
|
15
|
-
import {
|
|
16
|
-
import { MLInferenceNode, MLInferenceNodeType } from "./MLInferenceNode";
|
|
15
|
+
import { AINode, AINodeType } from "./AINode";
|
|
17
16
|
import { LogicNode, LogicNodeType } from "./LogicNode";
|
|
18
17
|
import { DataNode, DataNodeType } from "./DataNode";
|
|
19
18
|
import { TriggerNode, TriggerNodeType } from "./TriggerNode";
|
|
@@ -25,8 +24,7 @@ export type NodeOutput = { name: string; dataType: DataType };
|
|
|
25
24
|
export type NodeType =
|
|
26
25
|
| InputNodeType
|
|
27
26
|
| OutputNodeType
|
|
28
|
-
|
|
|
29
|
-
| MLInferenceNodeType
|
|
27
|
+
| AINodeType
|
|
30
28
|
| LogicNodeType
|
|
31
29
|
| DataNodeType
|
|
32
30
|
| TriggerNodeType
|
|
@@ -39,7 +37,7 @@ export type NodeType =
|
|
|
39
37
|
* It is a union type of all specific node types, each with their own typed parameters.
|
|
40
38
|
* Use this type when you need strong typing for a specific node.
|
|
41
39
|
*/
|
|
42
|
-
export type NodeData = InputNode | OutputNode |
|
|
40
|
+
export type NodeData = InputNode | OutputNode | AINode | LogicNode | DataNode | TriggerNode | ToolNode | FunctionCallNode | MqttNode;
|
|
43
41
|
|
|
44
42
|
/**
|
|
45
43
|
* Full domain node entity held on a {@link Canvas}: the {@link NodeData}
|
package/src/node/NodeRegistry.ts
CHANGED
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
// Copyright (c) 2026 ForestHub.
|
|
3
3
|
|
|
4
4
|
import { ReadPinNodeDefinition, SerialReadNodeDefinition, RetrieverNodeDefinition, WebFetchNodeDefinition, CameraCaptureNodeDefinition } from "./InputNode";
|
|
5
|
-
import { AgentNodeDefinition } from "./
|
|
6
|
-
import { MLInferenceNodeDefinition } from "./MLInferenceNode";
|
|
5
|
+
import { AgentNodeDefinition, MLInferenceNodeDefinition } from "./AINode";
|
|
7
6
|
import {
|
|
8
7
|
DelayNodeDefinition,
|
|
9
8
|
TickerNodeDefinition,
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
-
// Copyright (c) 2026 ForestHub.
|
|
3
|
-
|
|
4
|
-
import { NodeBase } from "./Node";
|
|
5
|
-
import type { Reference } from "../api";
|
|
6
|
-
import { OutputBinding } from "../parameter";
|
|
7
|
-
import { NodeCategory } from "./constants";
|
|
8
|
-
import { NodeDefinition } from "./NodeDefinition";
|
|
9
|
-
|
|
10
|
-
// MLInference — runs a declared ML model on an input and returns its result.
|
|
11
|
-
// The model is selected from the workflow's declared MLModels; the input is a
|
|
12
|
-
// reference to a variable whose value is fed to the model, and the result is
|
|
13
|
-
// emitted as a string.
|
|
14
|
-
export interface MLInferenceNode extends NodeBase {
|
|
15
|
-
type: "MLInference";
|
|
16
|
-
arguments: {
|
|
17
|
-
model: string;
|
|
18
|
-
input: Reference | undefined;
|
|
19
|
-
output: OutputBinding;
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export type MLInferenceNodeType = "MLInference";
|
|
24
|
-
|
|
25
|
-
export const MLInferenceNodeDefinition: NodeDefinition = {
|
|
26
|
-
type: "MLInference",
|
|
27
|
-
label: "ML Inference",
|
|
28
|
-
category: NodeCategory.AI,
|
|
29
|
-
description: "Runs a machine-learning model on an input and returns its result",
|
|
30
|
-
outputs: [{ id: "output", label: "Result", type: "static", dataType: "string" }],
|
|
31
|
-
parameters: [
|
|
32
|
-
{
|
|
33
|
-
id: "model",
|
|
34
|
-
label: "Model",
|
|
35
|
-
description: "ML model to run",
|
|
36
|
-
type: "modelSelect",
|
|
37
|
-
modelType: ["MLModel"],
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
id: "input",
|
|
41
|
-
label: "Input",
|
|
42
|
-
description: "Variable whose value is fed to the model",
|
|
43
|
-
type: "variableSelect",
|
|
44
|
-
},
|
|
45
|
-
],
|
|
46
|
-
};
|