@oomol-lab/open-flow 0.1.0-beta.56 → 0.1.0-beta.58
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/browser/{createResourceDialog-Btjes3wD.js → createResourceDialog-C23SBjYd.js} +2 -2
- package/dist/browser/flow-authoring-node.d.ts +6 -2
- package/dist/browser/flow-authoring.js +44 -12
- package/dist/browser/flow-change-schema.d.ts +266 -0
- package/dist/browser/flow-change.d.ts +5 -0
- package/dist/browser/flow-change.js +33 -2
- package/dist/browser/{flowChanges-BxutPLYO.js → flowChanges-fBiAeTzR.js} +954 -487
- package/dist/browser/{flowWorkspace-Dg4mqfa6.js → flowWorkspace-MqcEfg7T.js} +3 -3
- package/dist/browser/{icons-p2A9zs8t.js → icons-6oQ8Q9Wm.js} +4298 -4252
- package/dist/browser/preview.js +354 -36
- package/dist/browser/workbench.js +21 -10
- package/dist/browser/{workbenchSelect-LRp_Xjeq.js → workbenchSelect-DpLbIr29.js} +1 -1
- package/dist/common/authoring.d.ts +207 -0
- package/dist/common/authoringSchema.d.ts +1293 -0
- package/dist/common/control-api-conformance.js +975 -505
- package/dist/common/control-api-errors.d.ts +2 -1
- package/dist/common/control-api.d.ts +81 -0
- package/dist/common/control-api.js +973 -586
- package/dist/common/control-requests.d.ts +128 -0
- package/dist/common/control-requests.js +3122 -346
- package/dist/common/decision.js +12 -2
- package/dist/common/flow-encoding.js +12 -2
- package/dist/common/flow-semantics.d.ts +9 -0
- package/dist/common/flow-semantics.js +28 -3
- package/dist/common/integration-trigger.js +12 -2
- package/dist/common/lib-DrKav3HG.js +11403 -0
- package/dist/common/mcp.d.ts +120 -11
- package/dist/common/mcp.js +423 -51
- package/dist/common/openapi.js +12 -2
- package/dist/common/poll-trigger.js +12 -2
- package/dist/common/scheduler.js +12 -2
- package/dist/common/webhook-trigger.js +12 -2
- package/package.json +7 -1
- package/skills/open-flow/SKILL.md +32 -0
- package/skills/open-flow/references/flow-authoring.md +356 -0
- package/skills/open-flow/references/flow-n8n-conversion.md +196 -0
|
@@ -265,7 +265,7 @@ function safeExtend(schema, shape) {
|
|
|
265
265
|
if (!isPlainObject$1(shape)) throw new Error("Invalid input to safeExtend: expected a plain object");
|
|
266
266
|
return clone(schema, mergeDefs(schema._zod.def, { shape: extended(schema, shape) }));
|
|
267
267
|
}
|
|
268
|
-
function merge(a, b) {
|
|
268
|
+
function merge$1(a, b) {
|
|
269
269
|
if (!b?._zod?.def) throw new Error("Invalid input to merge: expected an object schema. To merge a plain shape, use `.extend()`.");
|
|
270
270
|
if (a._zod.def.checks?.length) throw new Error(".merge() cannot be used on object schemas containing refinements. Use .safeExtend() instead.");
|
|
271
271
|
const newShape = {};
|
|
@@ -5506,7 +5506,7 @@ var ZodObject = /*@__PURE__*/ $constructor("ZodObject", (inst, def) => {
|
|
|
5506
5506
|
return safeExtend(this, incoming);
|
|
5507
5507
|
},
|
|
5508
5508
|
merge(other) {
|
|
5509
|
-
return merge(this, other);
|
|
5509
|
+
return merge$1(this, other);
|
|
5510
5510
|
},
|
|
5511
5511
|
pick(mask) {
|
|
5512
5512
|
return pick$1(this, mask);
|
|
@@ -5584,7 +5584,7 @@ var ZodRecord = /*@__PURE__*/ $constructor("ZodRecord", (inst, def) => {
|
|
|
5584
5584
|
inst.keyType = def.keyType;
|
|
5585
5585
|
inst.valueType = def.valueType;
|
|
5586
5586
|
});
|
|
5587
|
-
function record$
|
|
5587
|
+
function record$3(keyType, valueType, params) {
|
|
5588
5588
|
if (!valueType || !valueType._zod) return new ZodRecord({
|
|
5589
5589
|
type: "record",
|
|
5590
5590
|
keyType: string(),
|
|
@@ -5832,7 +5832,7 @@ function refine(fn, _params = {}) {
|
|
|
5832
5832
|
function superRefine(fn, params) {
|
|
5833
5833
|
return /* @__PURE__ */ _superRefine(fn, params);
|
|
5834
5834
|
}
|
|
5835
|
-
function json$
|
|
5835
|
+
function json$5(params) {
|
|
5836
5836
|
const jsonSchema = lazy(() => {
|
|
5837
5837
|
return union([
|
|
5838
5838
|
string(params),
|
|
@@ -5840,7 +5840,7 @@ function json$3(params) {
|
|
|
5840
5840
|
boolean(),
|
|
5841
5841
|
_null(),
|
|
5842
5842
|
array(jsonSchema),
|
|
5843
|
-
record$
|
|
5843
|
+
record$3(string(), jsonSchema)
|
|
5844
5844
|
]);
|
|
5845
5845
|
});
|
|
5846
5846
|
return jsonSchema;
|
|
@@ -5853,19 +5853,6 @@ function preprocess(fn, schema) {
|
|
|
5853
5853
|
});
|
|
5854
5854
|
}
|
|
5855
5855
|
//#endregion
|
|
5856
|
-
//#region src/execution/common/wait.ts
|
|
5857
|
-
/** Shared by decision entry points, the editor, and durable decision storage. */
|
|
5858
|
-
var waitCommentSchema = string().trim().refine((value) => [...value].length <= 2e3, "Wait comment must contain at most 2,000 Unicode code points.").nullable().optional();
|
|
5859
|
-
//#endregion
|
|
5860
|
-
//#region src/flow/common/inputValue.ts
|
|
5861
|
-
/** Converts explicit user values at authoring boundaries, never persisted legacy data. */
|
|
5862
|
-
function inputValues(values) {
|
|
5863
|
-
return Object.fromEntries(Object.entries(values).map(([name, value]) => [name, {
|
|
5864
|
-
kind: "value",
|
|
5865
|
-
value
|
|
5866
|
-
}]));
|
|
5867
|
-
}
|
|
5868
|
-
//#endregion
|
|
5869
5856
|
//#region ../../node_modules/.bun/dequal@2.0.3/node_modules/dequal/lite/index.mjs
|
|
5870
5857
|
var has = Object.prototype.hasOwnProperty;
|
|
5871
5858
|
function dequal(foo, bar) {
|
|
@@ -5914,9 +5901,9 @@ function deepCompareStrict(a, b) {
|
|
|
5914
5901
|
//#endregion
|
|
5915
5902
|
//#region ../../node_modules/.bun/@cfworker+json-schema@4.1.1/node_modules/@cfworker/json-schema/dist/esm/pointer.js
|
|
5916
5903
|
function encodePointer(p) {
|
|
5917
|
-
return encodeURI(escapePointer(p));
|
|
5904
|
+
return encodeURI(escapePointer$1(p));
|
|
5918
5905
|
}
|
|
5919
|
-
function escapePointer(p) {
|
|
5906
|
+
function escapePointer$1(p) {
|
|
5920
5907
|
return p.replace(/~/g, "~0").replace(/\//g, "~1");
|
|
5921
5908
|
}
|
|
5922
5909
|
//#endregion
|
|
@@ -6770,6 +6757,660 @@ var Validator = class {
|
|
|
6770
6757
|
}
|
|
6771
6758
|
};
|
|
6772
6759
|
//#endregion
|
|
6760
|
+
//#region src/openapi/common/authBindings.ts
|
|
6761
|
+
/** Never allow credentials to enter a Revision as literal node inputs. */
|
|
6762
|
+
function assertOpenApiAuthBindings(document) {
|
|
6763
|
+
for (const node of Object.values(document.graph.nodes)) {
|
|
6764
|
+
if (node.kind != "task" || !("executor" in node.task) || node.task.executor.kind != "openapi") continue;
|
|
6765
|
+
for (const [handle, mapping] of Object.entries(node.inputs)) if (handle.startsWith("auth.") && mapping.kind == "value") throw new TypeError("OpenAPI authentication accepts deployment variables and upstream outputs only.");
|
|
6766
|
+
}
|
|
6767
|
+
}
|
|
6768
|
+
//#endregion
|
|
6769
|
+
//#region src/flow/common/inputValue.ts
|
|
6770
|
+
/** Converts explicit user values at authoring boundaries, never persisted legacy data. */
|
|
6771
|
+
function inputValues(values) {
|
|
6772
|
+
return Object.fromEntries(Object.entries(values).map(([name, value]) => [name, {
|
|
6773
|
+
kind: "value",
|
|
6774
|
+
value
|
|
6775
|
+
}]));
|
|
6776
|
+
}
|
|
6777
|
+
//#endregion
|
|
6778
|
+
//#region src/flow/common/condition.ts
|
|
6779
|
+
var unaryOperator = (operator) => operator.startsWith("is");
|
|
6780
|
+
var operandHandle = (caseIndex, groupIndex, expressionIndex, side) => `${caseIndex}/${groupIndex}/${expressionIndex}/${side}`;
|
|
6781
|
+
/** Derived addresses let operand bindings use the ordinary input analysis and editor. Never persisted as node inputs. */
|
|
6782
|
+
function conditionOperands(node) {
|
|
6783
|
+
return node.cases.flatMap((item, c) => item.groups.flatMap((group, g) => group.expressions.flatMap((expression, e) => [{
|
|
6784
|
+
handle: operandHandle(c, g, e, "left"),
|
|
6785
|
+
operand: expression.left,
|
|
6786
|
+
expression,
|
|
6787
|
+
side: "left"
|
|
6788
|
+
}, ...!unaryOperator(expression.operator) ? [{
|
|
6789
|
+
handle: operandHandle(c, g, e, "right"),
|
|
6790
|
+
operand: expression.right ?? { kind: "value" },
|
|
6791
|
+
expression,
|
|
6792
|
+
side: "right"
|
|
6793
|
+
}] : []])));
|
|
6794
|
+
}
|
|
6795
|
+
function nodeInputMappings(node) {
|
|
6796
|
+
if (node.kind != "condition") return "inputs" in node ? node.inputs : {};
|
|
6797
|
+
return Object.fromEntries(conditionOperands(node).flatMap(({ handle, operand }) => operand.kind == "source" ? [[handle, {
|
|
6798
|
+
kind: "sources",
|
|
6799
|
+
sources: [operand.source]
|
|
6800
|
+
}]] : operand.value === void 0 ? [] : [[handle, {
|
|
6801
|
+
kind: "value",
|
|
6802
|
+
value: operand.value
|
|
6803
|
+
}]]));
|
|
6804
|
+
}
|
|
6805
|
+
function conditionInputPorts(node) {
|
|
6806
|
+
return Object.fromEntries(conditionOperands(node).map(({ handle, operand }) => [handle, {
|
|
6807
|
+
jsonSchema: operand.kind === "value" ? operand.jsonSchema ?? {} : {},
|
|
6808
|
+
nullable: operand.kind === "value" ? operand.value === null : true
|
|
6809
|
+
}]));
|
|
6810
|
+
}
|
|
6811
|
+
function setConditionInput(node, handle, mapping) {
|
|
6812
|
+
const entry = conditionOperands(node).find((item) => item.handle == handle);
|
|
6813
|
+
if (entry == null) throw new Error("Condition operand does not exist.");
|
|
6814
|
+
if (mapping?.kind == "sources" && mapping.sources.length != 1) throw new Error("A Condition operand requires one Source.");
|
|
6815
|
+
const value = mapping?.kind == "sources" ? {
|
|
6816
|
+
kind: "source",
|
|
6817
|
+
source: mapping.sources[0]
|
|
6818
|
+
} : {
|
|
6819
|
+
kind: "value",
|
|
6820
|
+
...entry.operand.kind === "value" && entry.operand.jsonSchema != null ? { jsonSchema: entry.operand.jsonSchema } : {},
|
|
6821
|
+
...mapping?.kind == "value" ? { value: mapping.value } : {}
|
|
6822
|
+
};
|
|
6823
|
+
const [c, g, e] = handle.split("/").map(Number);
|
|
6824
|
+
return {
|
|
6825
|
+
...node,
|
|
6826
|
+
cases: node.cases.map((item, ci) => ci != c ? item : {
|
|
6827
|
+
...item,
|
|
6828
|
+
groups: item.groups.map((group, gi) => gi != g ? group : {
|
|
6829
|
+
...group,
|
|
6830
|
+
expressions: group.expressions.map((expression, ei) => ei != e ? expression : {
|
|
6831
|
+
...expression,
|
|
6832
|
+
[entry.side]: value
|
|
6833
|
+
})
|
|
6834
|
+
})
|
|
6835
|
+
})
|
|
6836
|
+
};
|
|
6837
|
+
}
|
|
6838
|
+
function resourceNameIssue(value) {
|
|
6839
|
+
const name = value.trim();
|
|
6840
|
+
if (name.length == 0) return "empty";
|
|
6841
|
+
if (name.length > 80) return "tooLong";
|
|
6842
|
+
for (const character of name) {
|
|
6843
|
+
const code = character.charCodeAt(0);
|
|
6844
|
+
if (code <= 31 || code >= 127 && code <= 159) return "controlCharacter";
|
|
6845
|
+
}
|
|
6846
|
+
if (!/^[\p{L}\p{N}](?:[\p{L}\p{N} _-]*[\p{L}\p{N}])?$/u.test(name)) return "specialCharacter";
|
|
6847
|
+
}
|
|
6848
|
+
function portsByHandle(ports) {
|
|
6849
|
+
return Object.fromEntries(ports.flatMap((port) => "handle" in port ? [[port.handle, port]] : []));
|
|
6850
|
+
}
|
|
6851
|
+
function decodeConnectorCapabilities(value) {
|
|
6852
|
+
if (!Array.isArray(value)) throw new TypeError("Connector capabilities must be an array.");
|
|
6853
|
+
if (value.length == 0) return [];
|
|
6854
|
+
if (value.some((item) => item != null && typeof item == "object" && !Array.isArray(item) && Object.hasOwn(item, "mode"))) {
|
|
6855
|
+
if (value.length != 1) throw new TypeError("Connector capability is declared more than once.");
|
|
6856
|
+
const source = value[0];
|
|
6857
|
+
if (source.mode == "shared") {
|
|
6858
|
+
if (source.kind != "connector" || Object.keys(source).some((key) => !["kind", "mode"].includes(key))) throw new TypeError("Invalid shared Connector permission capability.");
|
|
6859
|
+
return [{
|
|
6860
|
+
kind: "connector",
|
|
6861
|
+
mode: "shared"
|
|
6862
|
+
}];
|
|
6863
|
+
}
|
|
6864
|
+
if (Object.keys(source).some((key) => ![
|
|
6865
|
+
"kind",
|
|
6866
|
+
"mode",
|
|
6867
|
+
"actions"
|
|
6868
|
+
].includes(key)) || source.kind != "connector" || source.mode != "independent" || !Array.isArray(source.actions)) throw new TypeError("Invalid Connector permission capability.");
|
|
6869
|
+
const actions = source.actions.map((entry) => {
|
|
6870
|
+
if (entry == null || typeof entry != "object" || Array.isArray(entry)) throw new TypeError("Invalid Connector Action.");
|
|
6871
|
+
const action = entry;
|
|
6872
|
+
if (Object.keys(action).some((key) => !["action", "connectionId"].includes(key)) || typeof action.action != "string" || !/^[A-Za-z0-9_-]+\.[A-Za-z0-9_.-]+$/.test(action.action) || Object.hasOwn(action, "connectionId") && (typeof action.connectionId != "string" || action.connectionId.length == 0)) throw new TypeError("Invalid Connector Action permission.");
|
|
6873
|
+
return action.connectionId == null ? { action: action.action } : {
|
|
6874
|
+
action: action.action,
|
|
6875
|
+
connectionId: action.connectionId
|
|
6876
|
+
};
|
|
6877
|
+
});
|
|
6878
|
+
if (new Set(actions.map((action) => action.action)).size != actions.length) throw new TypeError("Duplicate Connector Action permission.");
|
|
6879
|
+
return [{
|
|
6880
|
+
kind: "connector",
|
|
6881
|
+
mode: "independent",
|
|
6882
|
+
actions
|
|
6883
|
+
}];
|
|
6884
|
+
}
|
|
6885
|
+
if (value.some((item) => item != null && typeof item == "object" && !Array.isArray(item) && !Object.hasOwn(item, "action"))) {
|
|
6886
|
+
if (value.length != 1) throw new TypeError("Connector capability is declared more than once.");
|
|
6887
|
+
const item = value[0];
|
|
6888
|
+
if (item == null || typeof item != "object" || Array.isArray(item)) throw new TypeError("Invalid Connector capability.");
|
|
6889
|
+
const source = item;
|
|
6890
|
+
if (Object.keys(source).some((key) => ![
|
|
6891
|
+
"kind",
|
|
6892
|
+
"actionHints",
|
|
6893
|
+
"connectionHints"
|
|
6894
|
+
].includes(key)) || source.kind != "connector" || Object.hasOwn(source, "actionHints") && !Array.isArray(source.actionHints) || Object.hasOwn(source, "connectionHints") && !Array.isArray(source.connectionHints)) throw new TypeError("Invalid Connector capability.");
|
|
6895
|
+
const actionHints = (source.actionHints ?? []).map((action) => {
|
|
6896
|
+
if (typeof action != "string" || !/^[A-Za-z0-9_-]+\.[A-Za-z0-9_.-]+$/.test(action)) throw new TypeError("Invalid Connector Action hint.");
|
|
6897
|
+
return action;
|
|
6898
|
+
});
|
|
6899
|
+
if (new Set(actionHints).size != actionHints.length) throw new TypeError("Duplicate Connector Action hint.");
|
|
6900
|
+
const keys = /* @__PURE__ */ new Set();
|
|
6901
|
+
const connectionHints = (source.connectionHints ?? []).map((entry) => {
|
|
6902
|
+
if (entry == null || typeof entry != "object" || Array.isArray(entry)) throw new TypeError("Invalid Connector Connection hint.");
|
|
6903
|
+
const hint = entry;
|
|
6904
|
+
if (Object.keys(hint).some((key) => ![
|
|
6905
|
+
"action",
|
|
6906
|
+
"connectionId",
|
|
6907
|
+
"alias"
|
|
6908
|
+
].includes(key)) || typeof hint.action != "string" || !/^[A-Za-z0-9_-]+\.[A-Za-z0-9_.-]+$/.test(hint.action) || typeof hint.connectionId != "string" || hint.connectionId.length == 0 || Object.hasOwn(hint, "alias") && (typeof hint.alias != "string" || hint.alias.length == 0)) throw new TypeError("Invalid Connector Connection hint.");
|
|
6909
|
+
const key = `${hint.action}\0${hint.alias ?? ""}`;
|
|
6910
|
+
if (keys.has(key)) throw new TypeError("Duplicate Connector Connection hint.");
|
|
6911
|
+
keys.add(key);
|
|
6912
|
+
return hint.alias == null ? {
|
|
6913
|
+
action: hint.action,
|
|
6914
|
+
connectionId: hint.connectionId
|
|
6915
|
+
} : {
|
|
6916
|
+
action: hint.action,
|
|
6917
|
+
connectionId: hint.connectionId,
|
|
6918
|
+
alias: hint.alias
|
|
6919
|
+
};
|
|
6920
|
+
});
|
|
6921
|
+
return [{
|
|
6922
|
+
kind: "connector",
|
|
6923
|
+
...actionHints.length == 0 ? {} : { actionHints },
|
|
6924
|
+
...connectionHints.length == 0 ? {} : { connectionHints }
|
|
6925
|
+
}];
|
|
6926
|
+
}
|
|
6927
|
+
const actions = /* @__PURE__ */ new Set();
|
|
6928
|
+
return value.map((item) => {
|
|
6929
|
+
if (item == null || typeof item != "object" || Array.isArray(item)) throw new TypeError("Invalid Connector capability.");
|
|
6930
|
+
const source = item;
|
|
6931
|
+
if (Object.keys(source).some((key) => ![
|
|
6932
|
+
"kind",
|
|
6933
|
+
"action",
|
|
6934
|
+
"connections",
|
|
6935
|
+
"connectionId"
|
|
6936
|
+
].includes(key)) || source.kind != "connector" || typeof source.action != "string" || !/^[A-Za-z0-9_-]+\.[A-Za-z0-9_.-]+$/.test(source.action) || !Array.isArray(source.connections)) throw new TypeError("Invalid Connector capability.");
|
|
6937
|
+
if (actions.has(source.action)) throw new TypeError("Connector Action is declared more than once.");
|
|
6938
|
+
actions.add(source.action);
|
|
6939
|
+
const ids = /* @__PURE__ */ new Set();
|
|
6940
|
+
const aliases = /* @__PURE__ */ new Set();
|
|
6941
|
+
const connections = source.connections.map((entry) => {
|
|
6942
|
+
if (entry == null || typeof entry != "object" || Array.isArray(entry)) throw new TypeError("Invalid Connector Connection.");
|
|
6943
|
+
const connection = entry;
|
|
6944
|
+
if (Object.keys(connection).some((key) => !["connectionId", "alias"].includes(key)) || typeof connection.connectionId != "string" || connection.connectionId.length == 0 || ids.has(connection.connectionId)) throw new TypeError("Invalid or duplicate Connector Connection ID.");
|
|
6945
|
+
ids.add(connection.connectionId);
|
|
6946
|
+
if (Object.hasOwn(connection, "alias")) {
|
|
6947
|
+
if (typeof connection.alias != "string" || connection.alias.length == 0 || aliases.has(connection.alias)) throw new TypeError("Invalid or duplicate Connector alias.");
|
|
6948
|
+
aliases.add(connection.alias);
|
|
6949
|
+
}
|
|
6950
|
+
return {
|
|
6951
|
+
connectionId: connection.connectionId,
|
|
6952
|
+
...connection.alias == null ? {} : { alias: connection.alias }
|
|
6953
|
+
};
|
|
6954
|
+
});
|
|
6955
|
+
if (Object.hasOwn(source, "connectionId") && (typeof source.connectionId != "string" || !ids.has(source.connectionId))) throw new TypeError("The default Connector Connection must be declared.");
|
|
6956
|
+
return {
|
|
6957
|
+
kind: "connector",
|
|
6958
|
+
action: source.action,
|
|
6959
|
+
connections,
|
|
6960
|
+
...source.connectionId == null ? {} : { connectionId: source.connectionId }
|
|
6961
|
+
};
|
|
6962
|
+
});
|
|
6963
|
+
}
|
|
6964
|
+
function normalizeNodeName(value) {
|
|
6965
|
+
return value.trim().normalize("NFC");
|
|
6966
|
+
}
|
|
6967
|
+
function nodeNameIssue(graph, nodeId, value) {
|
|
6968
|
+
const name = normalizeNodeName(value);
|
|
6969
|
+
if (name.length == 0) return "empty";
|
|
6970
|
+
return Object.entries(graph.nodes).some(([candidateId, node]) => candidateId != nodeId && node.name != null && normalizeNodeName(node.name) == name) ? "duplicate" : void 0;
|
|
6971
|
+
}
|
|
6972
|
+
var FlowChangeError = class extends Error {
|
|
6973
|
+
constructor(message) {
|
|
6974
|
+
super(message);
|
|
6975
|
+
this.name = "FlowChangeError";
|
|
6976
|
+
}
|
|
6977
|
+
};
|
|
6978
|
+
function invalid(message) {
|
|
6979
|
+
throw new FlowChangeError(message);
|
|
6980
|
+
}
|
|
6981
|
+
function applyFlowChanges(content, operations) {
|
|
6982
|
+
const document = { ...content.document };
|
|
6983
|
+
const modules = { ...content.modules };
|
|
6984
|
+
for (const operation of operations) switch (operation.kind) {
|
|
6985
|
+
case "graph.trigger.sources.set": {
|
|
6986
|
+
const graph = document.graph;
|
|
6987
|
+
const node = graph.nodes[operation.nodeId];
|
|
6988
|
+
if (node?.kind != "error") invalid("The Flow Error node does not exist.");
|
|
6989
|
+
if (!dequal(node.sourceFlowIds, operation.before)) invalid("The Flow Error node’s sources changed before this operation was applied.");
|
|
6990
|
+
const { sourceFlowIds: _, ...base } = node;
|
|
6991
|
+
const updated = operation.value == null ? base : {
|
|
6992
|
+
...base,
|
|
6993
|
+
sourceFlowIds: operation.value
|
|
6994
|
+
};
|
|
6995
|
+
document.graph = {
|
|
6996
|
+
...graph,
|
|
6997
|
+
nodes: {
|
|
6998
|
+
...graph.nodes,
|
|
6999
|
+
[operation.nodeId]: updated
|
|
7000
|
+
}
|
|
7001
|
+
};
|
|
7002
|
+
break;
|
|
7003
|
+
}
|
|
7004
|
+
case "binding.create":
|
|
7005
|
+
if (document.bindings[operation.bindingId] != null) invalid("A Binding with this ID already exists.");
|
|
7006
|
+
document.bindings = {
|
|
7007
|
+
...document.bindings,
|
|
7008
|
+
[operation.bindingId]: operation.binding
|
|
7009
|
+
};
|
|
7010
|
+
break;
|
|
7011
|
+
case "binding.delete": {
|
|
7012
|
+
if (document.bindings[operation.bindingId] == null) invalid("The Binding does not exist.");
|
|
7013
|
+
const bindings = { ...document.bindings };
|
|
7014
|
+
delete bindings[operation.bindingId];
|
|
7015
|
+
document.bindings = bindings;
|
|
7016
|
+
break;
|
|
7017
|
+
}
|
|
7018
|
+
case "binding.target.set": {
|
|
7019
|
+
const binding = document.bindings[operation.bindingId];
|
|
7020
|
+
if (binding == null) invalid("The Binding does not exist.");
|
|
7021
|
+
if (binding.target != operation.before) invalid("The Binding target changed before this operation was applied.");
|
|
7022
|
+
document.bindings = {
|
|
7023
|
+
...document.bindings,
|
|
7024
|
+
[operation.bindingId]: {
|
|
7025
|
+
...binding,
|
|
7026
|
+
target: operation.value
|
|
7027
|
+
}
|
|
7028
|
+
};
|
|
7029
|
+
break;
|
|
7030
|
+
}
|
|
7031
|
+
case "graph.edge.connect": {
|
|
7032
|
+
const graph = document.graph;
|
|
7033
|
+
if (graph.nodes[operation.edge.source] == null) invalid("The source Node does not exist.");
|
|
7034
|
+
const node = graph.nodes[operation.edge.target];
|
|
7035
|
+
if (node == null || !("inputs" in node)) invalid("The target Node does not accept execution dependencies.");
|
|
7036
|
+
if (graph.edges.some((edge) => dequal(edge, operation.edge))) invalid("The Nodes are already connected.");
|
|
7037
|
+
Object.assign(document, { graph: {
|
|
7038
|
+
...graph,
|
|
7039
|
+
edges: [...graph.edges, operation.edge]
|
|
7040
|
+
} });
|
|
7041
|
+
break;
|
|
7042
|
+
}
|
|
7043
|
+
case "graph.edge.disconnect": {
|
|
7044
|
+
const graph = document.graph;
|
|
7045
|
+
const edges = graph.edges.filter((edge) => !dequal(edge, operation.edge));
|
|
7046
|
+
if (edges.length == graph.edges.length) invalid("The Nodes are not connected.");
|
|
7047
|
+
Object.assign(document, { graph: {
|
|
7048
|
+
...graph,
|
|
7049
|
+
edges
|
|
7050
|
+
} });
|
|
7051
|
+
break;
|
|
7052
|
+
}
|
|
7053
|
+
case "graph.node.additional-inputs.set": {
|
|
7054
|
+
const graph = document.graph;
|
|
7055
|
+
const node = graph.nodes[operation.nodeId];
|
|
7056
|
+
if (node?.kind != "task") invalid("The Task Node does not exist.");
|
|
7057
|
+
if (!dequal(node.additionalInputs, operation.before)) invalid("The Task Node inputs changed before this operation was applied.");
|
|
7058
|
+
const { additionalInputs: _, ...rest } = node;
|
|
7059
|
+
const updated = operation.value == null ? rest : {
|
|
7060
|
+
...rest,
|
|
7061
|
+
additionalInputs: operation.value
|
|
7062
|
+
};
|
|
7063
|
+
Object.assign(document, { graph: {
|
|
7064
|
+
...graph,
|
|
7065
|
+
nodes: {
|
|
7066
|
+
...graph.nodes,
|
|
7067
|
+
[operation.nodeId]: updated
|
|
7068
|
+
}
|
|
7069
|
+
} });
|
|
7070
|
+
break;
|
|
7071
|
+
}
|
|
7072
|
+
case "graph.node.condition.set": {
|
|
7073
|
+
const graph = document.graph;
|
|
7074
|
+
const node = graph.nodes[operation.nodeId];
|
|
7075
|
+
if (node?.kind != "condition") invalid("The Condition Node does not exist.");
|
|
7076
|
+
if (!dequal(node.cases, operation.before.cases) || node.matchMode != operation.before.matchMode) invalid("The Condition Node changed before this operation was applied.");
|
|
7077
|
+
const updated = {
|
|
7078
|
+
...node,
|
|
7079
|
+
...operation.value
|
|
7080
|
+
};
|
|
7081
|
+
Object.assign(document, { graph: {
|
|
7082
|
+
...graph,
|
|
7083
|
+
nodes: {
|
|
7084
|
+
...graph.nodes,
|
|
7085
|
+
[operation.nodeId]: updated
|
|
7086
|
+
}
|
|
7087
|
+
} });
|
|
7088
|
+
break;
|
|
7089
|
+
}
|
|
7090
|
+
case "graph.node.replace": {
|
|
7091
|
+
const graph = document.graph;
|
|
7092
|
+
if (!dequal(graph.nodes[operation.nodeId], operation.before)) invalid("The Node changed before this operation was applied.");
|
|
7093
|
+
if (operation.node.kind != operation.before.kind) invalid("Replacing a Node cannot change its kind.");
|
|
7094
|
+
if (operation.node.kind == "task" && "moduleId" in operation.node.task && operation.node.task.capabilities !== void 0) decodeConnectorCapabilities(operation.node.task.capabilities);
|
|
7095
|
+
const name = normalizeNodeName(operation.node.name ?? "");
|
|
7096
|
+
const issue = nodeNameIssue(graph, operation.nodeId, name);
|
|
7097
|
+
if (issue != null) invalid(`Node name is ${issue}.`);
|
|
7098
|
+
const node = name == operation.node.name ? operation.node : {
|
|
7099
|
+
...operation.node,
|
|
7100
|
+
name
|
|
7101
|
+
};
|
|
7102
|
+
Object.assign(document, { graph: {
|
|
7103
|
+
...graph,
|
|
7104
|
+
nodes: {
|
|
7105
|
+
...graph.nodes,
|
|
7106
|
+
[operation.nodeId]: node
|
|
7107
|
+
}
|
|
7108
|
+
} });
|
|
7109
|
+
break;
|
|
7110
|
+
}
|
|
7111
|
+
case "graph.node.create": {
|
|
7112
|
+
const graph = document.graph;
|
|
7113
|
+
if (graph.nodes[operation.nodeId] != null) invalid("A Node with this ID already exists in the target graph.");
|
|
7114
|
+
if (operation.node.kind == "error" && Object.values(graph.nodes).some((node) => node.kind == "error")) invalid("A graph can contain only one Flow Error node.");
|
|
7115
|
+
if (operation.node.kind == "manual" && Object.values(graph.nodes).some((node) => node.kind == "manual")) invalid("A graph can contain only one manual Trigger.");
|
|
7116
|
+
if (operation.node.kind == "task" && "moduleId" in operation.node.task && operation.node.task.capabilities !== void 0) decodeConnectorCapabilities(operation.node.task.capabilities);
|
|
7117
|
+
if (operation.node.name == null) invalid("A Node name cannot be empty.");
|
|
7118
|
+
const name = normalizeNodeName(operation.node.name);
|
|
7119
|
+
const issue = nodeNameIssue(graph, operation.nodeId, name);
|
|
7120
|
+
if (issue == "empty") invalid("A Node name cannot be empty.");
|
|
7121
|
+
if (issue == "duplicate") invalid("A Node with this name already exists in the target graph.");
|
|
7122
|
+
const node = name == operation.node.name ? operation.node : {
|
|
7123
|
+
...operation.node,
|
|
7124
|
+
name
|
|
7125
|
+
};
|
|
7126
|
+
Object.assign(document, { graph: {
|
|
7127
|
+
...graph,
|
|
7128
|
+
nodes: {
|
|
7129
|
+
...graph.nodes,
|
|
7130
|
+
[operation.nodeId]: node
|
|
7131
|
+
}
|
|
7132
|
+
} });
|
|
7133
|
+
break;
|
|
7134
|
+
}
|
|
7135
|
+
case "graph.node.delete": {
|
|
7136
|
+
const graph = document.graph;
|
|
7137
|
+
if (graph.nodes[operation.nodeId] == null) invalid("The Node does not exist in the target graph.");
|
|
7138
|
+
const removed = /* @__PURE__ */ new Set([operation.nodeId]);
|
|
7139
|
+
const nodes = Object.fromEntries(Object.entries(graph.nodes).filter(([nodeId]) => !removed.has(nodeId)));
|
|
7140
|
+
Object.assign(document, { graph: {
|
|
7141
|
+
...graph,
|
|
7142
|
+
edges: graph.edges.filter((edge) => !removed.has(edge.source) && !removed.has(edge.target)),
|
|
7143
|
+
nodes
|
|
7144
|
+
} });
|
|
7145
|
+
break;
|
|
7146
|
+
}
|
|
7147
|
+
case "graph.node.field.set": {
|
|
7148
|
+
const graph = document.graph;
|
|
7149
|
+
const node = graph.nodes[operation.nodeId];
|
|
7150
|
+
if (node == null) invalid("The Node does not exist in the target graph.");
|
|
7151
|
+
if (operation.field == "connectionId" && node.kind != "poll" && node.kind != "integration") invalid("Only provider Triggers select a node Connection.");
|
|
7152
|
+
if (!dequal(Reflect.get(node, operation.field), operation.before)) invalid("The Node field changed before this operation was applied.");
|
|
7153
|
+
const updated = { ...node };
|
|
7154
|
+
if (operation.field == "name") {
|
|
7155
|
+
if (typeof operation.value != "string") invalid("A Node name cannot be empty.");
|
|
7156
|
+
const name = normalizeNodeName(operation.value);
|
|
7157
|
+
const issue = nodeNameIssue(graph, operation.nodeId, name);
|
|
7158
|
+
if (issue == "empty") invalid("A Node name cannot be empty.");
|
|
7159
|
+
if (issue == "duplicate") invalid("A Node with this name already exists in the target graph.");
|
|
7160
|
+
Object.assign(updated, { name });
|
|
7161
|
+
} else if (operation.value == null) Reflect.deleteProperty(updated, operation.field);
|
|
7162
|
+
else Object.assign(updated, { [operation.field]: operation.value });
|
|
7163
|
+
Object.assign(document, { graph: {
|
|
7164
|
+
...graph,
|
|
7165
|
+
nodes: {
|
|
7166
|
+
...graph.nodes,
|
|
7167
|
+
[operation.nodeId]: updated
|
|
7168
|
+
}
|
|
7169
|
+
} });
|
|
7170
|
+
break;
|
|
7171
|
+
}
|
|
7172
|
+
case "graph.node.input.set": {
|
|
7173
|
+
const graph = document.graph;
|
|
7174
|
+
const node = graph.nodes[operation.nodeId];
|
|
7175
|
+
if (node == null || !("inputs" in node)) invalid("The Node does not accept inputs.");
|
|
7176
|
+
if (!dequal(nodeInputMappings(node)[operation.handle], operation.before)) invalid("The Node input changed before this operation was applied.");
|
|
7177
|
+
const inputs = { ...node.inputs };
|
|
7178
|
+
if (operation.value == null) delete inputs[operation.handle];
|
|
7179
|
+
else inputs[operation.handle] = operation.value;
|
|
7180
|
+
Object.assign(document, { graph: {
|
|
7181
|
+
...graph,
|
|
7182
|
+
nodes: {
|
|
7183
|
+
...graph.nodes,
|
|
7184
|
+
[operation.nodeId]: node.kind == "condition" ? setConditionInput(node, operation.handle, operation.value) : {
|
|
7185
|
+
...node,
|
|
7186
|
+
inputs
|
|
7187
|
+
}
|
|
7188
|
+
}
|
|
7189
|
+
} });
|
|
7190
|
+
break;
|
|
7191
|
+
}
|
|
7192
|
+
case "graph.node.task.capabilities.set": {
|
|
7193
|
+
const graph = document.graph;
|
|
7194
|
+
const node = graph.nodes[operation.nodeId];
|
|
7195
|
+
if (node?.kind != "task" || !("moduleId" in node.task)) invalid("The inline Task Node does not exist.");
|
|
7196
|
+
if (!dequal(node.task.capabilities, operation.before)) invalid("The inline Task capabilities changed before this operation was applied.");
|
|
7197
|
+
const task = { ...node.task };
|
|
7198
|
+
if (operation.value === void 0) delete task.capabilities;
|
|
7199
|
+
else task.capabilities = decodeConnectorCapabilities(operation.value);
|
|
7200
|
+
Object.assign(document, { graph: {
|
|
7201
|
+
...graph,
|
|
7202
|
+
nodes: {
|
|
7203
|
+
...graph.nodes,
|
|
7204
|
+
[operation.nodeId]: {
|
|
7205
|
+
...node,
|
|
7206
|
+
task
|
|
7207
|
+
}
|
|
7208
|
+
}
|
|
7209
|
+
} });
|
|
7210
|
+
break;
|
|
7211
|
+
}
|
|
7212
|
+
case "graph.node.task.name.set": {
|
|
7213
|
+
const graph = document.graph;
|
|
7214
|
+
const node = graph.nodes[operation.nodeId];
|
|
7215
|
+
if (node?.kind != "task" || !("moduleId" in node.task)) invalid("The inline Task Node does not exist.");
|
|
7216
|
+
if (node.task.name != operation.before) invalid("The inline Task name changed before this operation was applied.");
|
|
7217
|
+
const updated = {
|
|
7218
|
+
...node,
|
|
7219
|
+
task: {
|
|
7220
|
+
...node.task,
|
|
7221
|
+
name: operation.value
|
|
7222
|
+
}
|
|
7223
|
+
};
|
|
7224
|
+
Object.assign(document, { graph: {
|
|
7225
|
+
...graph,
|
|
7226
|
+
nodes: {
|
|
7227
|
+
...graph.nodes,
|
|
7228
|
+
[operation.nodeId]: updated
|
|
7229
|
+
}
|
|
7230
|
+
} });
|
|
7231
|
+
break;
|
|
7232
|
+
}
|
|
7233
|
+
case "graph.node.task.ports.set": {
|
|
7234
|
+
const graph = document.graph;
|
|
7235
|
+
const node = graph.nodes[operation.nodeId];
|
|
7236
|
+
if (node?.kind != "task" || !("moduleId" in node.task)) invalid("The inline Task Node does not exist.");
|
|
7237
|
+
if (!dequal({
|
|
7238
|
+
inputs: node.task.inputs,
|
|
7239
|
+
outputs: node.task.outputs
|
|
7240
|
+
}, operation.before)) invalid("The inline Task ports changed before this operation was applied.");
|
|
7241
|
+
const updated = {
|
|
7242
|
+
...node,
|
|
7243
|
+
task: {
|
|
7244
|
+
...node.task,
|
|
7245
|
+
inputs: operation.value.inputs,
|
|
7246
|
+
outputs: operation.value.outputs
|
|
7247
|
+
}
|
|
7248
|
+
};
|
|
7249
|
+
Object.assign(document, { graph: {
|
|
7250
|
+
...graph,
|
|
7251
|
+
nodes: {
|
|
7252
|
+
...graph.nodes,
|
|
7253
|
+
[operation.nodeId]: updated
|
|
7254
|
+
}
|
|
7255
|
+
} });
|
|
7256
|
+
break;
|
|
7257
|
+
}
|
|
7258
|
+
case "graph.node.values.set": {
|
|
7259
|
+
const graph = document.graph;
|
|
7260
|
+
const node = graph.nodes[operation.nodeId];
|
|
7261
|
+
if (node?.kind != "value") invalid("The Value Node does not exist.");
|
|
7262
|
+
if (!dequal(node.values, operation.before)) invalid("The Value Node changed before this operation was applied.");
|
|
7263
|
+
Object.assign(document, { graph: {
|
|
7264
|
+
...graph,
|
|
7265
|
+
nodes: {
|
|
7266
|
+
...graph.nodes,
|
|
7267
|
+
[operation.nodeId]: {
|
|
7268
|
+
...node,
|
|
7269
|
+
values: operation.value
|
|
7270
|
+
}
|
|
7271
|
+
}
|
|
7272
|
+
} });
|
|
7273
|
+
break;
|
|
7274
|
+
}
|
|
7275
|
+
case "graph.node.resolution.set": {
|
|
7276
|
+
const graph = document.graph;
|
|
7277
|
+
const node = graph.nodes[operation.nodeId];
|
|
7278
|
+
if (node?.kind != "wait" && node?.kind != "approval" || !dequal({
|
|
7279
|
+
inputDefinitions: node.inputDefinitions,
|
|
7280
|
+
prompt: node.prompt
|
|
7281
|
+
}, operation.before)) invalid("The resolution node changed before this operation was applied.");
|
|
7282
|
+
const updated = {
|
|
7283
|
+
...node,
|
|
7284
|
+
...operation.value
|
|
7285
|
+
};
|
|
7286
|
+
document.graph = {
|
|
7287
|
+
...graph,
|
|
7288
|
+
nodes: {
|
|
7289
|
+
...graph.nodes,
|
|
7290
|
+
[operation.nodeId]: updated
|
|
7291
|
+
}
|
|
7292
|
+
};
|
|
7293
|
+
break;
|
|
7294
|
+
}
|
|
7295
|
+
case "graph.node.webhook.set": {
|
|
7296
|
+
const graph = document.graph;
|
|
7297
|
+
const node = graph.nodes[operation.nodeId];
|
|
7298
|
+
if (node?.kind != "webhook") invalid("The Webhook Node does not exist.");
|
|
7299
|
+
if (node.method != operation.before.method || !dequal(node.bodyFields, operation.before.bodyFields) || !dequal(node.options, operation.before.options)) invalid("The Webhook Node changed before this operation was applied.");
|
|
7300
|
+
const { options: _, ...rest } = node;
|
|
7301
|
+
const updated = operation.value.options == null ? {
|
|
7302
|
+
...rest,
|
|
7303
|
+
bodyFields: operation.value.bodyFields,
|
|
7304
|
+
method: operation.value.method
|
|
7305
|
+
} : {
|
|
7306
|
+
...node,
|
|
7307
|
+
...operation.value
|
|
7308
|
+
};
|
|
7309
|
+
Object.assign(document, { graph: {
|
|
7310
|
+
...graph,
|
|
7311
|
+
nodes: {
|
|
7312
|
+
...graph.nodes,
|
|
7313
|
+
[operation.nodeId]: updated
|
|
7314
|
+
}
|
|
7315
|
+
} });
|
|
7316
|
+
break;
|
|
7317
|
+
}
|
|
7318
|
+
case "graph.trigger.config.set": {
|
|
7319
|
+
const graph = document.graph;
|
|
7320
|
+
const node = graph.nodes[operation.nodeId];
|
|
7321
|
+
if (node == null || node.kind != "integration" && node.kind != "poll") invalid("The configurable Trigger Node does not exist.");
|
|
7322
|
+
if (!dequal(node.config[operation.name], operation.before)) invalid("The Trigger configuration changed before this operation was applied.");
|
|
7323
|
+
const config = { ...node.config };
|
|
7324
|
+
if (operation.value === void 0) delete config[operation.name];
|
|
7325
|
+
else config[operation.name] = operation.value;
|
|
7326
|
+
document.graph = {
|
|
7327
|
+
...graph,
|
|
7328
|
+
nodes: {
|
|
7329
|
+
...graph.nodes,
|
|
7330
|
+
[operation.nodeId]: {
|
|
7331
|
+
...node,
|
|
7332
|
+
config
|
|
7333
|
+
}
|
|
7334
|
+
}
|
|
7335
|
+
};
|
|
7336
|
+
break;
|
|
7337
|
+
}
|
|
7338
|
+
case "graph.trigger.schedule.set": {
|
|
7339
|
+
const graph = document.graph;
|
|
7340
|
+
const node = graph.nodes[operation.nodeId];
|
|
7341
|
+
if (node == null || node.kind != "cron" && node.kind != "poll") invalid("The scheduled Trigger Node does not exist.");
|
|
7342
|
+
if (!dequal(node.kind == "cron" ? node.cronTimes : node.pollTimes, operation.before)) invalid("The Trigger schedule changed before this operation was applied.");
|
|
7343
|
+
const updated = node.kind == "cron" ? {
|
|
7344
|
+
...node,
|
|
7345
|
+
cronTimes: operation.value
|
|
7346
|
+
} : {
|
|
7347
|
+
...node,
|
|
7348
|
+
pollTimes: operation.value
|
|
7349
|
+
};
|
|
7350
|
+
document.graph = {
|
|
7351
|
+
...graph,
|
|
7352
|
+
nodes: {
|
|
7353
|
+
...graph.nodes,
|
|
7354
|
+
[operation.nodeId]: updated
|
|
7355
|
+
}
|
|
7356
|
+
};
|
|
7357
|
+
break;
|
|
7358
|
+
}
|
|
7359
|
+
case "module.create":
|
|
7360
|
+
if (modules[operation.moduleId] != null) invalid("A CodeModule with this ID already exists.");
|
|
7361
|
+
modules[operation.moduleId] = operation.module;
|
|
7362
|
+
break;
|
|
7363
|
+
case "module.delete":
|
|
7364
|
+
if (modules[operation.moduleId] == null) invalid("The CodeModule does not exist.");
|
|
7365
|
+
delete modules[operation.moduleId];
|
|
7366
|
+
break;
|
|
7367
|
+
case "module.rename": {
|
|
7368
|
+
const module = modules[operation.moduleId];
|
|
7369
|
+
if (module == null) invalid("The CodeModule does not exist.");
|
|
7370
|
+
if (module.name != operation.before) invalid("The CodeModule name changed before this operation was applied.");
|
|
7371
|
+
modules[operation.moduleId] = {
|
|
7372
|
+
...module,
|
|
7373
|
+
name: operation.name
|
|
7374
|
+
};
|
|
7375
|
+
break;
|
|
7376
|
+
}
|
|
7377
|
+
case "module.source.replace": {
|
|
7378
|
+
const module = modules[operation.moduleId];
|
|
7379
|
+
if (module == null) invalid("The CodeModule does not exist.");
|
|
7380
|
+
if (module.source != operation.beforeSource || !dequal(module.imports, operation.beforeImports)) invalid("The CodeModule source changed before this operation was applied.");
|
|
7381
|
+
modules[operation.moduleId] = {
|
|
7382
|
+
...module,
|
|
7383
|
+
imports: operation.imports,
|
|
7384
|
+
source: operation.source
|
|
7385
|
+
};
|
|
7386
|
+
break;
|
|
7387
|
+
}
|
|
7388
|
+
case "graph.node.task.set": {
|
|
7389
|
+
const graph = document.graph;
|
|
7390
|
+
const node = graph.nodes[operation.nodeId];
|
|
7391
|
+
if (node?.kind != "task") invalid("The Task Node does not exist.");
|
|
7392
|
+
if (!dequal(node.task, operation.before)) invalid("The Task configuration changed before this operation was applied.");
|
|
7393
|
+
document.graph = {
|
|
7394
|
+
...graph,
|
|
7395
|
+
nodes: {
|
|
7396
|
+
...graph.nodes,
|
|
7397
|
+
[operation.nodeId]: {
|
|
7398
|
+
...node,
|
|
7399
|
+
task: operation.value
|
|
7400
|
+
}
|
|
7401
|
+
}
|
|
7402
|
+
};
|
|
7403
|
+
break;
|
|
7404
|
+
}
|
|
7405
|
+
}
|
|
7406
|
+
assertOpenApiAuthBindings(document);
|
|
7407
|
+
return {
|
|
7408
|
+
document,
|
|
7409
|
+
modelVersion: 6,
|
|
7410
|
+
modules
|
|
7411
|
+
};
|
|
7412
|
+
}
|
|
7413
|
+
//#endregion
|
|
6773
7414
|
//#region src/json-schema-subset/utils.ts
|
|
6774
7415
|
var nextId = 0;
|
|
6775
7416
|
function createId() {
|
|
@@ -7189,7 +7830,7 @@ var ExpressionKind = Object.freeze({
|
|
|
7189
7830
|
});
|
|
7190
7831
|
//#endregion
|
|
7191
7832
|
//#region src/json-schema-subset/expression/expression.ts
|
|
7192
|
-
var expression = (delegate) => (e1, e2) => {
|
|
7833
|
+
var expression$1 = (delegate) => (e1, e2) => {
|
|
7193
7834
|
const rootNode = {
|
|
7194
7835
|
parent: null,
|
|
7195
7836
|
swapped: false,
|
|
@@ -9177,7 +9818,7 @@ function checkWithResult(extendsContext, schema1, schema2) {
|
|
|
9177
9818
|
const describe = describer();
|
|
9178
9819
|
const equals = schemaEqualsChecker(extendsContext);
|
|
9179
9820
|
context.isEquals = wrapEqualsCheckerWithCache(isDeepEquals);
|
|
9180
|
-
context.calculate = expression({
|
|
9821
|
+
context.calculate = expression$1({
|
|
9181
9822
|
describe,
|
|
9182
9823
|
equals,
|
|
9183
9824
|
calculate,
|
|
@@ -9705,16 +10346,19 @@ var webhookMethods = [
|
|
|
9705
10346
|
"PATCH",
|
|
9706
10347
|
"DELETE"
|
|
9707
10348
|
];
|
|
10349
|
+
function webhookSupportsBody(method) {
|
|
10350
|
+
return method !== "GET";
|
|
10351
|
+
}
|
|
9708
10352
|
var text$1 = string();
|
|
9709
|
-
var json$
|
|
10353
|
+
var json$4 = json$5();
|
|
9710
10354
|
var strings = array(text$1);
|
|
9711
10355
|
var port = object$1({
|
|
9712
10356
|
description: text$1.optional(),
|
|
9713
|
-
jsonSchema: json$
|
|
10357
|
+
jsonSchema: json$4,
|
|
9714
10358
|
nullable: boolean(),
|
|
9715
10359
|
handle: text$1
|
|
9716
10360
|
});
|
|
9717
|
-
var input = port.extend({ value: json$
|
|
10361
|
+
var input = port.extend({ value: json$4.optional() });
|
|
9718
10362
|
var group = object$1({
|
|
9719
10363
|
collapsed: boolean().optional(),
|
|
9720
10364
|
group: text$1
|
|
@@ -9730,13 +10374,13 @@ var source = union([object$1({
|
|
|
9730
10374
|
})]);
|
|
9731
10375
|
var fixedInput = union([object$1({ kind: literal("unset") }), object$1({
|
|
9732
10376
|
kind: literal("value"),
|
|
9733
|
-
value: json$
|
|
10377
|
+
value: json$4
|
|
9734
10378
|
})]);
|
|
9735
10379
|
var mapping = union([fixedInput, object$1({
|
|
9736
10380
|
kind: literal("sources"),
|
|
9737
10381
|
sources: array(source)
|
|
9738
10382
|
})]);
|
|
9739
|
-
var inputs$1 = record$
|
|
10383
|
+
var inputs$1 = record$3(text$1, mapping);
|
|
9740
10384
|
var ports = {
|
|
9741
10385
|
inputs: array(union([input, group])),
|
|
9742
10386
|
outputs: array(union([port, group]))
|
|
@@ -9781,7 +10425,7 @@ var inline = object$1({
|
|
|
9781
10425
|
});
|
|
9782
10426
|
var agentValue = union([object$1({
|
|
9783
10427
|
kind: literal("value"),
|
|
9784
|
-
value: json$
|
|
10428
|
+
value: json$4
|
|
9785
10429
|
}), object$1({
|
|
9786
10430
|
kind: literal("input"),
|
|
9787
10431
|
input: text$1
|
|
@@ -9813,7 +10457,7 @@ var decisionQuestion = discriminatedUnion("type", [
|
|
|
9813
10457
|
criteria: strings
|
|
9814
10458
|
})
|
|
9815
10459
|
]);
|
|
9816
|
-
var
|
|
10460
|
+
var managedFields = object$1({
|
|
9817
10461
|
...ports,
|
|
9818
10462
|
name: text$1,
|
|
9819
10463
|
executor: union([
|
|
@@ -9828,7 +10472,7 @@ var managed = object$1({
|
|
|
9828
10472
|
method: text$1,
|
|
9829
10473
|
path: text$1,
|
|
9830
10474
|
serverUrl: text$1,
|
|
9831
|
-
document: json$
|
|
10475
|
+
document: json$4,
|
|
9832
10476
|
auth: array(object$1({
|
|
9833
10477
|
id: text$1,
|
|
9834
10478
|
type: _enum([
|
|
@@ -9868,15 +10512,16 @@ var managed = object$1({
|
|
|
9868
10512
|
connectionId: text$1.optional(),
|
|
9869
10513
|
inputDefinitions: array(input),
|
|
9870
10514
|
messageHandle: text$1,
|
|
9871
|
-
inputs: record$
|
|
10515
|
+
inputs: record$3(text$1, agentValue)
|
|
9872
10516
|
}).optional()
|
|
9873
10517
|
})
|
|
9874
10518
|
])
|
|
9875
|
-
})
|
|
9876
|
-
var
|
|
10519
|
+
});
|
|
10520
|
+
var managed = managedFields.transform(limitDecisionTask);
|
|
10521
|
+
var operand$1 = union([object$1({
|
|
9877
10522
|
kind: literal("value"),
|
|
9878
|
-
value: json$
|
|
9879
|
-
jsonSchema: json$
|
|
10523
|
+
value: json$4.optional(),
|
|
10524
|
+
jsonSchema: json$4.optional()
|
|
9880
10525
|
}), object$1({
|
|
9881
10526
|
kind: literal("source"),
|
|
9882
10527
|
source
|
|
@@ -9887,7 +10532,7 @@ var condition = {
|
|
|
9887
10532
|
description: text$1.optional(),
|
|
9888
10533
|
output: text$1,
|
|
9889
10534
|
groups: array(object$1({ expressions: array(object$1({
|
|
9890
|
-
left: operand,
|
|
10535
|
+
left: operand$1,
|
|
9891
10536
|
operator: _enum([
|
|
9892
10537
|
"!=",
|
|
9893
10538
|
"<",
|
|
@@ -9910,7 +10555,7 @@ var condition = {
|
|
|
9910
10555
|
"notHasValue",
|
|
9911
10556
|
"startsWith"
|
|
9912
10557
|
]),
|
|
9913
|
-
right: operand.optional()
|
|
10558
|
+
right: operand$1.optional()
|
|
9914
10559
|
})) }))
|
|
9915
10560
|
}))
|
|
9916
10561
|
};
|
|
@@ -9923,7 +10568,7 @@ var webhookOptions = object$1({
|
|
|
9923
10568
|
allowedOrigins: strings.optional(),
|
|
9924
10569
|
noResponseBody: never().optional(),
|
|
9925
10570
|
responseData: text$1.optional(),
|
|
9926
|
-
responseHeaders: record$
|
|
10571
|
+
responseHeaders: record$3(text$1, text$1).optional(),
|
|
9927
10572
|
responseStatusCode: number().int().min(200).max(599).optional()
|
|
9928
10573
|
});
|
|
9929
10574
|
var webhook = {
|
|
@@ -9979,7 +10624,7 @@ var base = {
|
|
|
9979
10624
|
var node = union([
|
|
9980
10625
|
object$1({
|
|
9981
10626
|
...base,
|
|
9982
|
-
inputs: record$
|
|
10627
|
+
inputs: record$3(text$1, never()),
|
|
9983
10628
|
kind: literal("condition"),
|
|
9984
10629
|
...condition
|
|
9985
10630
|
}),
|
|
@@ -10028,7 +10673,7 @@ var node = union([
|
|
|
10028
10673
|
...trigger$1,
|
|
10029
10674
|
kind: literal("poll"),
|
|
10030
10675
|
connectionId: text$1.min(1).optional(),
|
|
10031
|
-
config: record$
|
|
10676
|
+
config: record$3(text$1, fixedInput),
|
|
10032
10677
|
definition: object$1({
|
|
10033
10678
|
...definition,
|
|
10034
10679
|
type: literal("poll")
|
|
@@ -10039,7 +10684,7 @@ var node = union([
|
|
|
10039
10684
|
...trigger$1,
|
|
10040
10685
|
kind: literal("integration"),
|
|
10041
10686
|
connectionId: text$1.min(1).optional(),
|
|
10042
|
-
config: record$
|
|
10687
|
+
config: record$3(text$1, fixedInput),
|
|
10043
10688
|
definition: object$1({
|
|
10044
10689
|
...definition,
|
|
10045
10690
|
type: literal("integration"),
|
|
@@ -10047,6 +10692,25 @@ var node = union([
|
|
|
10047
10692
|
})
|
|
10048
10693
|
})
|
|
10049
10694
|
]);
|
|
10695
|
+
/** Configuration schemas shared by the node authoring boundary. */
|
|
10696
|
+
var authoringDefinitionSchemas = {
|
|
10697
|
+
input,
|
|
10698
|
+
port,
|
|
10699
|
+
ports,
|
|
10700
|
+
condition: strictObject(condition),
|
|
10701
|
+
wait: strictObject(wait),
|
|
10702
|
+
webhook: strictObject(webhook),
|
|
10703
|
+
schedule: triggerScheduleSchema,
|
|
10704
|
+
capabilities: array(capability),
|
|
10705
|
+
connector: managedFields.shape.executor.options[0].omit({ kind: true }).strict(),
|
|
10706
|
+
openapi: managedFields.shape.executor.options[1].omit({ kind: true }).strict(),
|
|
10707
|
+
decision: managedFields.shape.executor.options[2].omit({ kind: true }).strict(),
|
|
10708
|
+
llm: managedFields.shape.executor.options[3].omit({ kind: true }).strict(),
|
|
10709
|
+
agent: managedFields.shape.executor.options[4].omit({
|
|
10710
|
+
kind: true,
|
|
10711
|
+
notification: true
|
|
10712
|
+
}).strict()
|
|
10713
|
+
};
|
|
10050
10714
|
var edge = object$1({
|
|
10051
10715
|
source: text$1,
|
|
10052
10716
|
target: text$1,
|
|
@@ -10057,7 +10721,7 @@ var at = {
|
|
|
10057
10721
|
target: never().optional()
|
|
10058
10722
|
};
|
|
10059
10723
|
var graph = object$1({
|
|
10060
|
-
nodes: record$
|
|
10724
|
+
nodes: record$3(text$1, node),
|
|
10061
10725
|
edges: array(edge).default([])
|
|
10062
10726
|
});
|
|
10063
10727
|
var binding = object$1({
|
|
@@ -10070,7 +10734,7 @@ var module = object$1({
|
|
|
10070
10734
|
source: text$1
|
|
10071
10735
|
});
|
|
10072
10736
|
var document = preprocess(rejectRetiredDefinitions, object$1({
|
|
10073
|
-
bindings: record$
|
|
10737
|
+
bindings: record$3(text$1, binding),
|
|
10074
10738
|
graph
|
|
10075
10739
|
}));
|
|
10076
10740
|
object$1({
|
|
@@ -10081,21 +10745,21 @@ object$1({
|
|
|
10081
10745
|
literal(6)
|
|
10082
10746
|
]),
|
|
10083
10747
|
document,
|
|
10084
|
-
modules: record$
|
|
10748
|
+
modules: record$3(text$1, module)
|
|
10085
10749
|
}).extend({
|
|
10086
10750
|
kind: literal("open-flow-flow-revision"),
|
|
10087
10751
|
version: literal(1)
|
|
10088
10752
|
});
|
|
10089
10753
|
function rejectRetiredDefinitions(value) {
|
|
10090
|
-
const candidate = record(value);
|
|
10754
|
+
const candidate = record$2(value);
|
|
10091
10755
|
if (candidate.tasks !== void 0 && (candidate.tasks === null || typeof candidate.tasks !== "object" || Array.isArray(candidate.tasks) || Object.keys(candidate.tasks).length > 0)) throw new TypeError("Independent Task definitions are no longer supported.");
|
|
10092
|
-
if (Object.values(record(record(candidate.graph).nodes)).some((candidateNode) => Object.hasOwn(record(candidateNode), "taskId"))) throw new TypeError("Task references are no longer supported.");
|
|
10756
|
+
if (Object.values(record$2(record$2(candidate.graph).nodes)).some((candidateNode) => Object.hasOwn(record$2(candidateNode), "taskId"))) throw new TypeError("Task references are no longer supported.");
|
|
10093
10757
|
const subflows = candidate.subflows;
|
|
10094
10758
|
if (subflows !== void 0 && (subflows === null || typeof subflows !== "object" || Array.isArray(subflows) || Object.keys(subflows).length > 0)) throw new TypeError("Subflows are no longer supported.");
|
|
10095
|
-
if (Object.values(record(record(candidate.graph).nodes)).some((candidateNode) => record(candidateNode).kind === "subflow")) throw new TypeError("Subflow nodes are no longer supported.");
|
|
10759
|
+
if (Object.values(record$2(record$2(candidate.graph).nodes)).some((candidateNode) => record$2(candidateNode).kind === "subflow")) throw new TypeError("Subflow nodes are no longer supported.");
|
|
10096
10760
|
return value;
|
|
10097
10761
|
}
|
|
10098
|
-
function record(value) {
|
|
10762
|
+
function record$2(value) {
|
|
10099
10763
|
return value != null && typeof value == "object" && !Array.isArray(value) ? value : {};
|
|
10100
10764
|
}
|
|
10101
10765
|
var shapes = {
|
|
@@ -10126,6 +10790,11 @@ var shapes = {
|
|
|
10126
10790
|
...at,
|
|
10127
10791
|
node
|
|
10128
10792
|
},
|
|
10793
|
+
"graph.node.replace": {
|
|
10794
|
+
...at,
|
|
10795
|
+
before: node,
|
|
10796
|
+
node
|
|
10797
|
+
},
|
|
10129
10798
|
"graph.node.delete": at,
|
|
10130
10799
|
"graph.node.field.set": union([
|
|
10131
10800
|
object$1({
|
|
@@ -10260,310 +10929,90 @@ function decodeChangeOperation(candidate, index) {
|
|
|
10260
10929
|
if (schema == null) throw new TypeError(`operations[${index}]: Unknown operation ${JSON.stringify(kind)}.`);
|
|
10261
10930
|
return parseOperation(candidate, index, schema.parse);
|
|
10262
10931
|
}
|
|
10932
|
+
function decodeChangeOperations(value) {
|
|
10933
|
+
checkJsonDepth(value);
|
|
10934
|
+
return array(unknown()).min(1).parse(value).map(decodeChangeOperation);
|
|
10935
|
+
}
|
|
10263
10936
|
function changeOperationsSchema(kind) {
|
|
10264
10937
|
const schema = kind == null ? operations : variants.get(kind);
|
|
10265
10938
|
if (schema == null) throw new TypeError(`Unknown operation ${JSON.stringify(kind)}.`);
|
|
10266
10939
|
return toJSONSchema(schema, { io: "input" });
|
|
10267
10940
|
}
|
|
10268
|
-
function resourceNameIssue(value) {
|
|
10269
|
-
const name = value.trim();
|
|
10270
|
-
if (name.length == 0) return "empty";
|
|
10271
|
-
if (name.length > 80) return "tooLong";
|
|
10272
|
-
for (const character of name) {
|
|
10273
|
-
const code = character.charCodeAt(0);
|
|
10274
|
-
if (code <= 31 || code >= 127 && code <= 159) return "controlCharacter";
|
|
10275
|
-
}
|
|
10276
|
-
if (!/^[\p{L}\p{N}](?:[\p{L}\p{N} _-]*[\p{L}\p{N}])?$/u.test(name)) return "specialCharacter";
|
|
10277
|
-
}
|
|
10278
10941
|
//#endregion
|
|
10279
|
-
//#region src/
|
|
10280
|
-
var
|
|
10281
|
-
|
|
10942
|
+
//#region src/control/common/authoringLlm.ts
|
|
10943
|
+
var authoringLlmConfiguration = strictObject({
|
|
10944
|
+
mode: _enum(["chat", "json"]),
|
|
10945
|
+
resultSchema: json$5(),
|
|
10946
|
+
model: json$5().optional().describe("Default model settings: {model, temperature?, top_p?, max_tokens?}. A bound model input takes precedence."),
|
|
10947
|
+
template: json$5().optional().describe("Default message templates: [{role: \"system\" | \"user\" | \"assistant\", content: \"Text with {{namedInput}}\"}]."),
|
|
10948
|
+
messages: json$5().optional().describe("Default conversation history, prepended without template interpolation; an array of {role, content} or null.")
|
|
10949
|
+
});
|
|
10950
|
+
var defaults = {
|
|
10951
|
+
model: "model",
|
|
10952
|
+
template: "template",
|
|
10953
|
+
messages: "messages"
|
|
10954
|
+
};
|
|
10955
|
+
/** Read defaults only. Node bindings remain independently visible and editable. */
|
|
10956
|
+
function llmConfigurationView(task) {
|
|
10957
|
+
if (task.executor.kind != "llm") throw new TypeError("Expected an LLM task.");
|
|
10958
|
+
const config = {
|
|
10959
|
+
mode: task.executor.mode,
|
|
10960
|
+
resultSchema: task.outputs.find((port) => "handle" in port)?.jsonSchema ?? {}
|
|
10961
|
+
};
|
|
10962
|
+
for (const [name, handle] of Object.entries(defaults)) {
|
|
10963
|
+
const port = task.inputs.find((candidate) => "handle" in candidate && candidate.handle == handle);
|
|
10964
|
+
if (port != null && Object.hasOwn(port, "value")) config[name] = port.value;
|
|
10965
|
+
}
|
|
10966
|
+
return config;
|
|
10282
10967
|
}
|
|
10283
|
-
|
|
10284
|
-
function
|
|
10285
|
-
|
|
10286
|
-
|
|
10287
|
-
|
|
10288
|
-
|
|
10289
|
-
|
|
10290
|
-
|
|
10291
|
-
|
|
10292
|
-
|
|
10293
|
-
|
|
10294
|
-
|
|
10295
|
-
|
|
10296
|
-
}
|
|
10297
|
-
|
|
10298
|
-
|
|
10299
|
-
|
|
10300
|
-
|
|
10301
|
-
|
|
10302
|
-
|
|
10303
|
-
|
|
10304
|
-
name
|
|
10305
|
-
},
|
|
10306
|
-
moduleId: identity.moduleId
|
|
10307
|
-
}, {
|
|
10308
|
-
kind: "graph.node.create",
|
|
10309
|
-
node: {
|
|
10310
|
-
inputs: defaultInputs(ports.inputs),
|
|
10311
|
-
kind: "task",
|
|
10312
|
-
name,
|
|
10313
|
-
task: {
|
|
10314
|
-
capabilities: ports.capabilities ?? [{
|
|
10315
|
-
kind: "connector",
|
|
10316
|
-
mode: "independent",
|
|
10317
|
-
actions: []
|
|
10318
|
-
}],
|
|
10319
|
-
inputs: ports.inputs,
|
|
10320
|
-
moduleId: identity.moduleId,
|
|
10321
|
-
name,
|
|
10322
|
-
outputs: ports.outputs
|
|
10323
|
-
}
|
|
10968
|
+
/** Update default values without altering port contracts, groups, or node bindings. */
|
|
10969
|
+
function prepareLlmConfiguration(config, previous, name) {
|
|
10970
|
+
if (previous.executor.kind != "llm") throw new TypeError("Expected an LLM task.");
|
|
10971
|
+
const old = llmConfigurationView(previous);
|
|
10972
|
+
const changed = Object.keys(defaults).filter((key) => Object.hasOwn(old, key) != Object.hasOwn(config, key) || !dequal(old[key], config[key]));
|
|
10973
|
+
const inputs = previous.inputs.map((port) => {
|
|
10974
|
+
if (!("handle" in port)) return port;
|
|
10975
|
+
const key = changed.find((candidate) => defaults[candidate] == port.handle);
|
|
10976
|
+
if (key == null) return port;
|
|
10977
|
+
const { value: _value, ...withoutDefault } = port;
|
|
10978
|
+
return Object.hasOwn(config, key) ? {
|
|
10979
|
+
...withoutDefault,
|
|
10980
|
+
value: config[key]
|
|
10981
|
+
} : withoutDefault;
|
|
10982
|
+
});
|
|
10983
|
+
return {
|
|
10984
|
+
...previous,
|
|
10985
|
+
name,
|
|
10986
|
+
executor: {
|
|
10987
|
+
...previous.executor,
|
|
10988
|
+
mode: config.mode
|
|
10324
10989
|
},
|
|
10325
|
-
|
|
10326
|
-
|
|
10990
|
+
inputs,
|
|
10991
|
+
outputs: dequal(old.resultSchema, config.resultSchema) ? previous.outputs : previous.outputs.map((port) => "handle" in port ? {
|
|
10992
|
+
...port,
|
|
10993
|
+
jsonSchema: config.resultSchema
|
|
10994
|
+
} : port)
|
|
10995
|
+
};
|
|
10327
10996
|
}
|
|
10328
|
-
|
|
10329
|
-
|
|
10330
|
-
|
|
10331
|
-
node: {
|
|
10332
|
-
inputs: defaultInputs(task.inputs),
|
|
10333
|
-
kind: "task",
|
|
10334
|
-
name: task.name,
|
|
10335
|
-
task
|
|
10336
|
-
},
|
|
10337
|
-
nodeId: identity.nodeId
|
|
10338
|
-
}];
|
|
10339
|
-
}
|
|
10340
|
-
function createLlmTask(identity, name, mode, outputDescription, options = {}) {
|
|
10341
|
-
const values = options.inputs ?? {};
|
|
10342
|
-
return createManagedTask(identity, {
|
|
10343
|
-
executor: {
|
|
10344
|
-
kind: "llm",
|
|
10345
|
-
mode
|
|
10346
|
-
},
|
|
10347
|
-
inputs: [
|
|
10348
|
-
{
|
|
10349
|
-
handle: "messages",
|
|
10350
|
-
jsonSchema: {
|
|
10351
|
-
items: { type: "object" },
|
|
10352
|
-
type: "array"
|
|
10353
|
-
},
|
|
10354
|
-
nullable: true,
|
|
10355
|
-
value: llmInputValue(values, "messages", null)
|
|
10356
|
-
},
|
|
10357
|
-
{
|
|
10358
|
-
handle: "input",
|
|
10359
|
-
jsonSchema: { type: "string" },
|
|
10360
|
-
nullable: false,
|
|
10361
|
-
value: llmInputValue(values, "input", "Alex")
|
|
10362
|
-
},
|
|
10363
|
-
{
|
|
10364
|
-
handle: "template",
|
|
10365
|
-
jsonSchema: {
|
|
10366
|
-
items: { type: "object" },
|
|
10367
|
-
minItems: 1,
|
|
10368
|
-
type: "array"
|
|
10369
|
-
},
|
|
10370
|
-
nullable: false,
|
|
10371
|
-
value: llmInputValue(values, "template", [{
|
|
10372
|
-
content: "Hello, I'm {{input}}",
|
|
10373
|
-
role: "user"
|
|
10374
|
-
}])
|
|
10375
|
-
},
|
|
10376
|
-
{
|
|
10377
|
-
handle: "model",
|
|
10378
|
-
jsonSchema: { type: "object" },
|
|
10379
|
-
nullable: false,
|
|
10380
|
-
value: llmInputValue(values, "model", { model: "deepseek-v4-flash" })
|
|
10381
|
-
}
|
|
10382
|
-
],
|
|
10383
|
-
name,
|
|
10384
|
-
outputs: [{
|
|
10385
|
-
...options.output,
|
|
10386
|
-
description: options.output?.description ?? outputDescription,
|
|
10387
|
-
handle: "output",
|
|
10388
|
-
jsonSchema: options.output?.jsonSchema ?? (mode == "chat" ? { type: "string" } : {}),
|
|
10389
|
-
nullable: options.output?.nullable ?? false
|
|
10390
|
-
}]
|
|
10391
|
-
});
|
|
10392
|
-
}
|
|
10393
|
-
function createCondition(nodeId, name) {
|
|
10394
|
-
return [{
|
|
10395
|
-
kind: "graph.node.create",
|
|
10396
|
-
node: {
|
|
10397
|
-
cases: [{
|
|
10398
|
-
groups: [{ expressions: [{
|
|
10399
|
-
left: { kind: "value" },
|
|
10400
|
-
operator: "==",
|
|
10401
|
-
right: { kind: "value" }
|
|
10402
|
-
}] }],
|
|
10403
|
-
output: "case"
|
|
10404
|
-
}],
|
|
10405
|
-
matchMode: "first",
|
|
10406
|
-
inputs: {},
|
|
10407
|
-
kind: "condition",
|
|
10408
|
-
name
|
|
10409
|
-
},
|
|
10410
|
-
nodeId
|
|
10411
|
-
}];
|
|
10412
|
-
}
|
|
10413
|
-
function createValue(nodeId, name) {
|
|
10414
|
-
return [{
|
|
10415
|
-
kind: "graph.node.create",
|
|
10416
|
-
node: {
|
|
10417
|
-
inputs: {},
|
|
10418
|
-
kind: "value",
|
|
10419
|
-
name,
|
|
10420
|
-
values: [{
|
|
10421
|
-
handle: "value",
|
|
10422
|
-
jsonSchema: {},
|
|
10423
|
-
nullable: true,
|
|
10424
|
-
value: null
|
|
10425
|
-
}]
|
|
10426
|
-
},
|
|
10427
|
-
nodeId
|
|
10428
|
-
}];
|
|
10429
|
-
}
|
|
10430
|
-
function createWait(nodeId, name) {
|
|
10431
|
-
return [{
|
|
10432
|
-
kind: "graph.node.create",
|
|
10433
|
-
node: {
|
|
10434
|
-
inputDefinitions: [],
|
|
10435
|
-
inputs: {},
|
|
10436
|
-
kind: "wait",
|
|
10437
|
-
name,
|
|
10438
|
-
prompt: name
|
|
10439
|
-
},
|
|
10440
|
-
nodeId
|
|
10441
|
-
}];
|
|
10442
|
-
}
|
|
10443
|
-
function createApproval(nodeId, name) {
|
|
10444
|
-
return [{
|
|
10445
|
-
kind: "graph.node.create",
|
|
10446
|
-
node: {
|
|
10447
|
-
inputDefinitions: [],
|
|
10448
|
-
inputs: {},
|
|
10449
|
-
kind: "approval",
|
|
10450
|
-
name,
|
|
10451
|
-
prompt: name
|
|
10452
|
-
},
|
|
10453
|
-
nodeId
|
|
10454
|
-
}];
|
|
10455
|
-
}
|
|
10456
|
-
function createBuiltinTrigger(nodeId, node) {
|
|
10457
|
-
return [{
|
|
10458
|
-
kind: "graph.node.create",
|
|
10459
|
-
node,
|
|
10460
|
-
nodeId
|
|
10461
|
-
}];
|
|
10462
|
-
}
|
|
10463
|
-
function createProviderTrigger(nodeId, definition, options) {
|
|
10464
|
-
const name = options.name ?? definition.displayName;
|
|
10465
|
-
return [{
|
|
10466
|
-
kind: "graph.node.create",
|
|
10467
|
-
node: definition.type == "poll" ? {
|
|
10468
|
-
...options.connectionId == null ? {} : { connectionId: options.connectionId },
|
|
10469
|
-
config: inputValues(options.config),
|
|
10470
|
-
definition,
|
|
10471
|
-
kind: "poll",
|
|
10472
|
-
name,
|
|
10473
|
-
pollTimes: options.schedule ?? [{
|
|
10474
|
-
type: "every",
|
|
10475
|
-
unit: "minute",
|
|
10476
|
-
value: 5
|
|
10477
|
-
}]
|
|
10478
|
-
} : {
|
|
10479
|
-
...options.connectionId == null ? {} : { connectionId: options.connectionId },
|
|
10480
|
-
config: inputValues(options.config),
|
|
10481
|
-
definition,
|
|
10482
|
-
kind: "integration",
|
|
10483
|
-
name
|
|
10484
|
-
},
|
|
10485
|
-
nodeId
|
|
10486
|
-
}];
|
|
10487
|
-
}
|
|
10488
|
-
function defaultInputs(ports) {
|
|
10489
|
-
return Object.fromEntries(ports.flatMap((port) => "handle" in port && Object.hasOwn(port, "value") ? [[port.handle, {
|
|
10490
|
-
kind: "value",
|
|
10491
|
-
value: port.value
|
|
10492
|
-
}]] : []));
|
|
10493
|
-
}
|
|
10494
|
-
function llmInputValue(values, handle, fallback) {
|
|
10495
|
-
return values != null && Object.hasOwn(values, handle) ? values[handle] : fallback;
|
|
10496
|
-
}
|
|
10497
|
-
function createDecisionTask(identity, name = "AI Decision", questions) {
|
|
10498
|
-
return createManagedTask(identity, decisionTask(questions, name));
|
|
10499
|
-
}
|
|
10500
|
-
//#endregion
|
|
10501
|
-
//#region src/control/common/draftOperations.ts
|
|
10502
|
-
var text = string().min(1);
|
|
10503
|
-
var json$1 = json$3();
|
|
10504
|
-
var triggerCreate = strictObject({
|
|
10505
|
-
kind: literal("graph.trigger.create"),
|
|
10506
|
-
nodeId: text,
|
|
10507
|
-
key: text,
|
|
10508
|
-
connectionId: text.optional(),
|
|
10509
|
-
name: text.optional(),
|
|
10510
|
-
config: record$1(text, json$1),
|
|
10511
|
-
schedule: triggerScheduleSchema.readonly().optional()
|
|
10512
|
-
});
|
|
10513
|
-
function decodeDraftOperations(value) {
|
|
10514
|
-
checkJsonDepth(value);
|
|
10515
|
-
return array(unknown()).min(1).parse(value).map((candidate, index) => {
|
|
10516
|
-
const { kind } = parseOperation(candidate, index, object$1({ kind: text }).parse);
|
|
10517
|
-
return kind == "graph.trigger.create" ? parseOperation(candidate, index, triggerCreate.parse) : decodeChangeOperation(candidate, index);
|
|
10518
|
-
});
|
|
10519
|
-
}
|
|
10520
|
-
function draftOperationsSchema(kind) {
|
|
10521
|
-
if (kind != null && kind != "graph.trigger.create") return changeOperationsSchema(kind);
|
|
10522
|
-
const trigger = toJSONSchema(triggerCreate);
|
|
10523
|
-
if (kind == "graph.trigger.create") return trigger;
|
|
10524
|
-
const schema = changeOperationsSchema();
|
|
10997
|
+
/** Keep the production LLM factory's contracts while removing sample business data. */
|
|
10998
|
+
function initialAuthoringLlmTask(task) {
|
|
10999
|
+
if (task.executor.kind != "llm") throw new TypeError("Expected an LLM task.");
|
|
10525
11000
|
return {
|
|
10526
|
-
...
|
|
10527
|
-
|
|
11001
|
+
...task,
|
|
11002
|
+
inputs: task.inputs.flatMap((port) => {
|
|
11003
|
+
if (!("handle" in port)) return [port];
|
|
11004
|
+
if (port.handle == "input") return [];
|
|
11005
|
+
if (port.handle == "template") return [{
|
|
11006
|
+
...port,
|
|
11007
|
+
value: [{
|
|
11008
|
+
role: "user",
|
|
11009
|
+
content: ""
|
|
11010
|
+
}]
|
|
11011
|
+
}];
|
|
11012
|
+
return [port];
|
|
11013
|
+
})
|
|
10528
11014
|
};
|
|
10529
11015
|
}
|
|
10530
|
-
function resolveDraftOperations(operations, definition) {
|
|
10531
|
-
return operations.flatMap((operation) => {
|
|
10532
|
-
if (operation.kind != "graph.trigger.create") return [operation];
|
|
10533
|
-
const snapshot = definition(operation.key);
|
|
10534
|
-
if (snapshot.type != "poll" && operation.schedule != null) throw new Error("Only Poll triggers accept a schedule.");
|
|
10535
|
-
return createProviderTrigger(operation.nodeId, snapshot, operation);
|
|
10536
|
-
});
|
|
10537
|
-
}
|
|
10538
|
-
//#endregion
|
|
10539
|
-
//#region src/control/common/eventSourceSchemas.ts
|
|
10540
|
-
var id$1 = string().min(1).max(256);
|
|
10541
|
-
var eventType = string().regex(/^[a-z][a-z0-9_.]{0,127}$/);
|
|
10542
|
-
var name = string().trim().min(1).max(128);
|
|
10543
|
-
var secret = string().min(1).max(256);
|
|
10544
|
-
var createEventSourceSchema = strictObject({
|
|
10545
|
-
version: literal(1),
|
|
10546
|
-
name,
|
|
10547
|
-
connectionId: id$1,
|
|
10548
|
-
teamId: id$1.nullable(),
|
|
10549
|
-
verificationToken: secret,
|
|
10550
|
-
encryptKey: secret,
|
|
10551
|
-
eventTypes: array(eventType).min(1).max(200).refine((values) => new Set(values).size == values.length),
|
|
10552
|
-
manageSubscriptions: boolean()
|
|
10553
|
-
});
|
|
10554
|
-
var updateEventSourceSchema = strictObject({
|
|
10555
|
-
version: literal(1),
|
|
10556
|
-
expectedRevision: int().positive(),
|
|
10557
|
-
name,
|
|
10558
|
-
enabled: boolean(),
|
|
10559
|
-
eventTypes: array(eventType).min(1).max(200).refine((values) => new Set(values).size == values.length),
|
|
10560
|
-
verificationToken: secret.optional(),
|
|
10561
|
-
encryptKey: secret.optional()
|
|
10562
|
-
});
|
|
10563
|
-
var eventSourceRevisionSchema = strictObject({
|
|
10564
|
-
version: literal(1),
|
|
10565
|
-
expectedRevision: int().positive()
|
|
10566
|
-
});
|
|
10567
11016
|
//#endregion
|
|
10568
11017
|
//#region src/openapi/common/openapi.ts
|
|
10569
11018
|
var methods = [
|
|
@@ -10948,6 +11397,2323 @@ function selectOperation(value, sourceUrl, path, method) {
|
|
|
10948
11397
|
return config;
|
|
10949
11398
|
}
|
|
10950
11399
|
//#endregion
|
|
11400
|
+
//#region src/control/common/authoringOpenApi.ts
|
|
11401
|
+
var authenticationSchema = union([
|
|
11402
|
+
strictObject({ schemes: array(string().min(1)).describe("One complete security alternative advertised by this operation; [] selects no authentication.") }),
|
|
11403
|
+
strictObject({ type: _enum(["bearer", "basic"]) }),
|
|
11404
|
+
strictObject({
|
|
11405
|
+
type: literal("apiKey"),
|
|
11406
|
+
name: string().min(1),
|
|
11407
|
+
in: _enum(["header", "query"])
|
|
11408
|
+
})
|
|
11409
|
+
]);
|
|
11410
|
+
var authoringOpenApiSchema = strictObject({
|
|
11411
|
+
sourceUrl: string().min(1),
|
|
11412
|
+
path: string().min(1),
|
|
11413
|
+
method: string().min(1),
|
|
11414
|
+
serverUrl: string().optional(),
|
|
11415
|
+
authentication: authenticationSchema.optional().describe("Omit to use the operation default. Bind credentials through the advertised node inputs.")
|
|
11416
|
+
});
|
|
11417
|
+
function openApiAuthenticationChoices(config) {
|
|
11418
|
+
try {
|
|
11419
|
+
return securityOptions(config.document, config.path, config.method).map(({ label, auth, error }) => Object.assign({ label }, auth == null ? { error } : { authentication: { schemes: auth.map((item) => item.id) } }));
|
|
11420
|
+
} catch (error) {
|
|
11421
|
+
return [{
|
|
11422
|
+
label: "Saved operation",
|
|
11423
|
+
error: error.message
|
|
11424
|
+
}];
|
|
11425
|
+
}
|
|
11426
|
+
}
|
|
11427
|
+
function authenticationView(config) {
|
|
11428
|
+
const schemes = config.auth.map((item) => item.id);
|
|
11429
|
+
if (!openApiAuthenticationChoices(config).some((option) => "authentication" in option && dequal(option.authentication?.schemes, schemes)) && config.auth.length == 1) {
|
|
11430
|
+
const { id: _id, ...manual } = config.auth[0];
|
|
11431
|
+
return manual;
|
|
11432
|
+
}
|
|
11433
|
+
return { schemes };
|
|
11434
|
+
}
|
|
11435
|
+
function openApiConfigView(config) {
|
|
11436
|
+
return {
|
|
11437
|
+
sourceUrl: config.sourceUrl,
|
|
11438
|
+
path: config.path,
|
|
11439
|
+
method: config.method,
|
|
11440
|
+
serverUrl: config.serverUrl,
|
|
11441
|
+
authentication: authenticationView(config)
|
|
11442
|
+
};
|
|
11443
|
+
}
|
|
11444
|
+
var AuthoringOpenApiAuthenticationError = class extends Error {
|
|
11445
|
+
constructor(config) {
|
|
11446
|
+
super("Choose one complete authentication alternative advertised by this operation, or configure manual authentication.");
|
|
11447
|
+
this.code = "openapi.authentication-invalid";
|
|
11448
|
+
this.name = "AuthoringOpenApiAuthenticationError";
|
|
11449
|
+
this.details = {
|
|
11450
|
+
field: "config.authentication",
|
|
11451
|
+
choices: openApiAuthenticationChoices(config)
|
|
11452
|
+
};
|
|
11453
|
+
}
|
|
11454
|
+
};
|
|
11455
|
+
function prepareAuthentication(config, choice) {
|
|
11456
|
+
if (!("schemes" in choice)) return [{
|
|
11457
|
+
id: "manual",
|
|
11458
|
+
...choice
|
|
11459
|
+
}];
|
|
11460
|
+
const names = new Set(choice.schemes);
|
|
11461
|
+
const matched = securityOptions(config.document, config.path, config.method).find((option) => option.auth != null && names.size == choice.schemes.length && option.auth.length == names.size && option.auth.every((auth) => names.has(auth.id)));
|
|
11462
|
+
if (matched?.auth == null) throw new AuthoringOpenApiAuthenticationError(config);
|
|
11463
|
+
return matched.auth;
|
|
11464
|
+
}
|
|
11465
|
+
/** Operation snapshots and credential handles remain stable until their business selection changes. */
|
|
11466
|
+
async function prepareOpenApiTask(config, previous, fetch, name, explicit = {}) {
|
|
11467
|
+
const current = previous?.executor.kind == "openapi" ? previous.executor : void 0;
|
|
11468
|
+
const changed = current == null || config.sourceUrl != current.sourceUrl || config.path != current.path || config.method != current.method;
|
|
11469
|
+
const authentication = changed && current != null && !explicit.authentication ? void 0 : config.authentication;
|
|
11470
|
+
let selected;
|
|
11471
|
+
if (!changed) selected = current;
|
|
11472
|
+
else {
|
|
11473
|
+
const document = await fetch(config.sourceUrl);
|
|
11474
|
+
if (authentication != null && !("schemes" in authentication)) {
|
|
11475
|
+
const saved = snapshot(document, config.path, config.method);
|
|
11476
|
+
selected = {
|
|
11477
|
+
kind: "openapi",
|
|
11478
|
+
sourceUrl: httpUrl(config.sourceUrl),
|
|
11479
|
+
path: config.path,
|
|
11480
|
+
method: config.method,
|
|
11481
|
+
serverUrl: serverAddress(servers(saved, config.path, config.method)[0], config.sourceUrl),
|
|
11482
|
+
document: saved,
|
|
11483
|
+
auth: []
|
|
11484
|
+
};
|
|
11485
|
+
} else selected = selectOperation(document, config.sourceUrl, config.path, config.method);
|
|
11486
|
+
}
|
|
11487
|
+
const defaultAuth = () => {
|
|
11488
|
+
const defaultSelection = securityOptions(current.document, current.path, current.method).find((option) => option.auth != null)?.auth;
|
|
11489
|
+
if (defaultSelection == null) throw new AuthoringOpenApiAuthenticationError(current);
|
|
11490
|
+
return defaultSelection;
|
|
11491
|
+
};
|
|
11492
|
+
const auth = authentication == null ? !changed && explicit.authentication ? defaultAuth() : selected.auth : !changed && dequal(authentication, authenticationView(current)) ? current.auth : prepareAuthentication(selected, authentication);
|
|
11493
|
+
const serverUrl = !changed && explicit.serverUrl && config.serverUrl == null ? serverAddress(servers(current.document, current.path, current.method)[0], current.sourceUrl) : changed && current != null && !explicit.serverUrl ? selected.serverUrl : config.serverUrl ?? selected.serverUrl;
|
|
11494
|
+
const executor = {
|
|
11495
|
+
...selected,
|
|
11496
|
+
auth,
|
|
11497
|
+
serverUrl
|
|
11498
|
+
};
|
|
11499
|
+
if (previous != null && !changed && dequal(auth, current.auth)) return {
|
|
11500
|
+
...previous,
|
|
11501
|
+
name,
|
|
11502
|
+
executor
|
|
11503
|
+
};
|
|
11504
|
+
return openApiTask(executor, name);
|
|
11505
|
+
}
|
|
11506
|
+
//#endregion
|
|
11507
|
+
//#region src/control/common/authoringSchema.ts
|
|
11508
|
+
var id$2 = string().min(1);
|
|
11509
|
+
var json$3 = json$5();
|
|
11510
|
+
var patch = record$3(id$2, json$3);
|
|
11511
|
+
var authoringTypes = [
|
|
11512
|
+
"manual",
|
|
11513
|
+
"webhook",
|
|
11514
|
+
"cron",
|
|
11515
|
+
"error",
|
|
11516
|
+
"poll",
|
|
11517
|
+
"integration",
|
|
11518
|
+
"code",
|
|
11519
|
+
"connector",
|
|
11520
|
+
"agent",
|
|
11521
|
+
"llm",
|
|
11522
|
+
"decision",
|
|
11523
|
+
"openapi",
|
|
11524
|
+
"condition",
|
|
11525
|
+
"value",
|
|
11526
|
+
"wait",
|
|
11527
|
+
"approval"
|
|
11528
|
+
];
|
|
11529
|
+
var type = _enum(authoringTypes);
|
|
11530
|
+
var referenceSchema = id$2.describe("An existing node reference returned by read/search, or $alias for a preceding node.add in this edit batch. For node.add.as \"step\", reference \"$step\", never bare \"step\". Aliases are local to one batch.");
|
|
11531
|
+
var output = strictObject({
|
|
11532
|
+
kind: literal("output"),
|
|
11533
|
+
node: referenceSchema,
|
|
11534
|
+
port: id$2.optional().describe("Omit for a node with one output. For multiple outputs, choose a name from node details."),
|
|
11535
|
+
field: string().optional()
|
|
11536
|
+
});
|
|
11537
|
+
var variable = strictObject({
|
|
11538
|
+
kind: literal("variable"),
|
|
11539
|
+
name: id$2
|
|
11540
|
+
});
|
|
11541
|
+
var authoringSourceSchema = union([
|
|
11542
|
+
output,
|
|
11543
|
+
variable,
|
|
11544
|
+
strictObject({
|
|
11545
|
+
kind: literal("value"),
|
|
11546
|
+
value: json$3
|
|
11547
|
+
}),
|
|
11548
|
+
strictObject({ kind: literal("unset") }),
|
|
11549
|
+
strictObject({ kind: literal("default") }),
|
|
11550
|
+
strictObject({
|
|
11551
|
+
kind: literal("sources"),
|
|
11552
|
+
sources: array(union([output, variable])).min(1)
|
|
11553
|
+
})
|
|
11554
|
+
]);
|
|
11555
|
+
var operand = union([
|
|
11556
|
+
strictObject({
|
|
11557
|
+
kind: literal("value"),
|
|
11558
|
+
value: json$3.optional(),
|
|
11559
|
+
schema: json$3.optional()
|
|
11560
|
+
}),
|
|
11561
|
+
output,
|
|
11562
|
+
variable
|
|
11563
|
+
]);
|
|
11564
|
+
var agentTool = authoringDefinitionSchemas.agent.shape.tools.element.omit({
|
|
11565
|
+
id: true,
|
|
11566
|
+
inputs: true
|
|
11567
|
+
}).extend({ inputs: record$3(id$2, authoringDefinitionSchemas.agent.shape.tools.element.shape.inputs.element.shape.source).optional().describe("Action input sources by name. The tool resolves types from the Action. New inputs default to model-provided; existing sources are preserved when omitted.") }).strict();
|
|
11568
|
+
var notification = strictObject({
|
|
11569
|
+
...authoringDefinitionSchemas.connector.shape,
|
|
11570
|
+
messageHandle: id$2,
|
|
11571
|
+
inputs: record$3(id$2, union([strictObject({
|
|
11572
|
+
kind: literal("value"),
|
|
11573
|
+
value: json$3
|
|
11574
|
+
}), strictObject({
|
|
11575
|
+
kind: literal("input"),
|
|
11576
|
+
input: id$2
|
|
11577
|
+
})]))
|
|
11578
|
+
});
|
|
11579
|
+
var field = strictObject({
|
|
11580
|
+
schema: json$3.optional(),
|
|
11581
|
+
nullable: boolean().optional(),
|
|
11582
|
+
description: string().optional()
|
|
11583
|
+
});
|
|
11584
|
+
var inputFields = record$3(id$2, field.extend({ default: json$3.optional() })).describe("Optional business input constraints by name. A binding to a new Code, Agent, LLM, Wait or Approval input automatically declares an input accepting any JSON. Existing constraints are preserved. Omitted schema accepts any JSON; omitted nullable is true. Use default for inherited values; input.set supplies data.");
|
|
11585
|
+
var outputFields = record$3(id$2, field).describe("Code return fields by name. Omitted schema accepts any JSON; omitted nullable is true.");
|
|
11586
|
+
var expression = strictObject({
|
|
11587
|
+
left: operand,
|
|
11588
|
+
operator: authoringDefinitionSchemas.condition.shape.cases.element.shape.groups.element.shape.expressions.element.shape.operator,
|
|
11589
|
+
right: operand.optional()
|
|
11590
|
+
});
|
|
11591
|
+
var all = strictObject({ all: array(expression) });
|
|
11592
|
+
var when = union([
|
|
11593
|
+
expression,
|
|
11594
|
+
all,
|
|
11595
|
+
strictObject({ any: array(union([expression, all])) })
|
|
11596
|
+
]);
|
|
11597
|
+
var authoringConfigurations = {
|
|
11598
|
+
manual: strictObject({}),
|
|
11599
|
+
error: strictObject({ sourceFlowIds: array(id$2).optional() }),
|
|
11600
|
+
webhook: authoringDefinitionSchemas.webhook.omit({ bodyFields: true }).extend({ body: inputFields }).strict(),
|
|
11601
|
+
cron: strictObject({ schedule: authoringDefinitionSchemas.schedule }),
|
|
11602
|
+
poll: strictObject({
|
|
11603
|
+
key: id$2,
|
|
11604
|
+
connectionId: id$2.optional(),
|
|
11605
|
+
schedule: authoringDefinitionSchemas.schedule
|
|
11606
|
+
}),
|
|
11607
|
+
integration: strictObject({
|
|
11608
|
+
key: id$2,
|
|
11609
|
+
connectionId: id$2.optional()
|
|
11610
|
+
}),
|
|
11611
|
+
code: strictObject({
|
|
11612
|
+
inputs: inputFields,
|
|
11613
|
+
outputs: outputFields,
|
|
11614
|
+
capabilities: authoringDefinitionSchemas.capabilities.optional()
|
|
11615
|
+
}),
|
|
11616
|
+
connector: authoringDefinitionSchemas.connector.strict(),
|
|
11617
|
+
openapi: authoringOpenApiSchema,
|
|
11618
|
+
agent: authoringDefinitionSchemas.agent.omit({
|
|
11619
|
+
prompt: true,
|
|
11620
|
+
tools: true
|
|
11621
|
+
}).extend({
|
|
11622
|
+
inputs: inputFields,
|
|
11623
|
+
resultSchema: json$3.describe("JSON schema of the final result. Defaults to text. The tool manages the output definition; references can omit port."),
|
|
11624
|
+
tools: array(agentTool),
|
|
11625
|
+
notification: notification.optional()
|
|
11626
|
+
}).strict(),
|
|
11627
|
+
llm: authoringLlmConfiguration.extend({ inputs: inputFields }),
|
|
11628
|
+
decision: authoringDefinitionSchemas.decision,
|
|
11629
|
+
condition: strictObject({
|
|
11630
|
+
match: _enum(["first", "all"]),
|
|
11631
|
+
branches: array(strictObject({
|
|
11632
|
+
name: id$2,
|
|
11633
|
+
description: string().optional(),
|
|
11634
|
+
when
|
|
11635
|
+
}))
|
|
11636
|
+
}),
|
|
11637
|
+
value: strictObject({
|
|
11638
|
+
values: patch,
|
|
11639
|
+
outputs: outputFields
|
|
11640
|
+
}),
|
|
11641
|
+
wait: strictObject({ inputs: inputFields }),
|
|
11642
|
+
approval: strictObject({ inputs: inputFields })
|
|
11643
|
+
};
|
|
11644
|
+
var updates = strictObject({
|
|
11645
|
+
name: id$2.optional(),
|
|
11646
|
+
description: string().optional(),
|
|
11647
|
+
icon: string().optional(),
|
|
11648
|
+
maxExecutions: int().positive().optional(),
|
|
11649
|
+
timeoutMs: number().nonnegative().optional(),
|
|
11650
|
+
config: patch.optional().describe("Recursively merge configuration; omitted fields remain unchanged and arrays replace as a whole. This includes schema objects: {} does not clear an existing schema. Use clear paths to remove fields, e.g. [\"config\",\"inputs\",\"amount\",\"schema\",\"type\"].")
|
|
11651
|
+
});
|
|
11652
|
+
var authoringEditSchema = discriminatedUnion("op", [
|
|
11653
|
+
strictObject({
|
|
11654
|
+
op: literal("node.add"),
|
|
11655
|
+
as: id$2.regex(/^[A-Za-z][\w-]*$/).describe("Unique batch-local alias without the $ prefix. Later edits must reference this new node as $alias; the bare alias is not its node ID."),
|
|
11656
|
+
type,
|
|
11657
|
+
name: id$2,
|
|
11658
|
+
config: patch.optional(),
|
|
11659
|
+
inputs: record$3(id$2, authoringSourceSchema).optional().describe("Input data sources, applied after creation, as input.set operations. Execution edges are separate."),
|
|
11660
|
+
code: string().optional(),
|
|
11661
|
+
prompt: string().optional()
|
|
11662
|
+
}),
|
|
11663
|
+
strictObject({
|
|
11664
|
+
op: literal("node.update"),
|
|
11665
|
+
node: referenceSchema,
|
|
11666
|
+
set: updates.optional(),
|
|
11667
|
+
clear: array(array(id$2).min(1)).optional()
|
|
11668
|
+
}),
|
|
11669
|
+
strictObject({
|
|
11670
|
+
op: literal("node.remove"),
|
|
11671
|
+
node: referenceSchema
|
|
11672
|
+
}),
|
|
11673
|
+
strictObject({
|
|
11674
|
+
op: literal("input.set"),
|
|
11675
|
+
node: referenceSchema,
|
|
11676
|
+
input: id$2,
|
|
11677
|
+
source: authoringSourceSchema
|
|
11678
|
+
}),
|
|
11679
|
+
strictObject({
|
|
11680
|
+
op: _enum(["edge.connect", "edge.disconnect"]),
|
|
11681
|
+
source: referenceSchema,
|
|
11682
|
+
target: referenceSchema,
|
|
11683
|
+
branch: id$2.optional()
|
|
11684
|
+
}),
|
|
11685
|
+
strictObject({
|
|
11686
|
+
op: literal("text.edit"),
|
|
11687
|
+
node: referenceSchema,
|
|
11688
|
+
field: _enum(["code", "prompt"]),
|
|
11689
|
+
oldText: id$2,
|
|
11690
|
+
newText: string()
|
|
11691
|
+
}),
|
|
11692
|
+
strictObject({
|
|
11693
|
+
op: literal("text.set"),
|
|
11694
|
+
node: referenceSchema,
|
|
11695
|
+
field: _enum(["code", "prompt"]),
|
|
11696
|
+
text: string()
|
|
11697
|
+
})
|
|
11698
|
+
]);
|
|
11699
|
+
var authoringRequestSchema = strictObject({
|
|
11700
|
+
baseRevision: id$2,
|
|
11701
|
+
requestId: id$2.max(256),
|
|
11702
|
+
edits: array(authoringEditSchema).min(1).max(1e3)
|
|
11703
|
+
});
|
|
11704
|
+
var authoringReadSchema = strictObject({
|
|
11705
|
+
revision: id$2.optional().describe("Fixed revision from a previous read; omit to read the current draft."),
|
|
11706
|
+
nodes: array(id$2).min(1).max(100).optional().describe("Node references to read in one batch. Mutually exclusive with text. Long texts return metadata."),
|
|
11707
|
+
text: strictObject({
|
|
11708
|
+
node: id$2,
|
|
11709
|
+
field: _enum(["code", "prompt"]),
|
|
11710
|
+
start: int().positive().default(1),
|
|
11711
|
+
lines: int().min(1).max(200).default(80)
|
|
11712
|
+
}).optional().describe("Read code or prompt by line (1-based). Mutually exclusive with nodes. Follow nextStart at the same revision until truncated is false.")
|
|
11713
|
+
}).refine((v) => v.nodes == null || v.text == null, "Choose nodes or text.").meta({
|
|
11714
|
+
not: { required: ["nodes", "text"] },
|
|
11715
|
+
description: "Omit nodes and text for an outline; provide nodes for details, or text for an excerpt."
|
|
11716
|
+
});
|
|
11717
|
+
var authoringCheckSchema = strictObject({ revisionId: id$2 });
|
|
11718
|
+
var authoringSearchSchema = strictObject({
|
|
11719
|
+
revision: id$2.optional(),
|
|
11720
|
+
query: id$2.max(1e3),
|
|
11721
|
+
type: type.optional(),
|
|
11722
|
+
offset: int().nonnegative().default(0),
|
|
11723
|
+
limit: int().min(1).max(100).default(20)
|
|
11724
|
+
});
|
|
11725
|
+
var authoringSchemaQuery = strictObject({
|
|
11726
|
+
type: type.optional(),
|
|
11727
|
+
action: id$2.optional()
|
|
11728
|
+
}).refine((v) => v.type == null || v.action == null, "Choose type or action.");
|
|
11729
|
+
var requestContracts = {
|
|
11730
|
+
read: {
|
|
11731
|
+
schema: authoringReadSchema,
|
|
11732
|
+
guidance: "Choose one mode: outline (omit nodes and text), node details (nodes), or text excerpt (text). nodes and text are mutually exclusive. Text defaults to 80 lines, at most 200 lines and 24000 characters. For the complete text, repeat at nextStart with the same revision until truncated is false.",
|
|
11733
|
+
examples: [
|
|
11734
|
+
{},
|
|
11735
|
+
{
|
|
11736
|
+
revision: "REVISION",
|
|
11737
|
+
nodes: ["NODE"]
|
|
11738
|
+
},
|
|
11739
|
+
{
|
|
11740
|
+
revision: "REVISION",
|
|
11741
|
+
text: {
|
|
11742
|
+
node: "NODE",
|
|
11743
|
+
field: "prompt",
|
|
11744
|
+
start: 1,
|
|
11745
|
+
lines: 80
|
|
11746
|
+
}
|
|
11747
|
+
}
|
|
11748
|
+
]
|
|
11749
|
+
},
|
|
11750
|
+
search: {
|
|
11751
|
+
schema: authoringSearchSchema,
|
|
11752
|
+
guidance: "Search names, configurations and text. Keep the returned revision when following nextOffset or reading a match.",
|
|
11753
|
+
examples: [{
|
|
11754
|
+
query: "Customer summary",
|
|
11755
|
+
type: "agent"
|
|
11756
|
+
}]
|
|
11757
|
+
},
|
|
11758
|
+
edit: {
|
|
11759
|
+
schema: authoringRequestSchema,
|
|
11760
|
+
guidance: "Use the observed revision as baseRevision and a stable requestId. Edits are ordered and atomic. node.add.as declares a batch-local alias without $. Every later reference to that new node must use $alias, including node, edge source/target and output source node fields; a bare alias is not the node ID. Use returned node references in later batches. Updates recursively merge objects (including schemas); {} preserves existing fields. Arrays replace as a whole. Remove fields with clear paths. Text replacement requires exactly one match. Read the target text first. A saved draft can have validation diagnostics.",
|
|
11761
|
+
examples: [{
|
|
11762
|
+
baseRevision: "REVISION",
|
|
11763
|
+
requestId: "CREATE_REQUEST",
|
|
11764
|
+
edits: [
|
|
11765
|
+
{
|
|
11766
|
+
op: "node.add",
|
|
11767
|
+
as: "start",
|
|
11768
|
+
type: "manual",
|
|
11769
|
+
name: "Start"
|
|
11770
|
+
},
|
|
11771
|
+
{
|
|
11772
|
+
op: "node.add",
|
|
11773
|
+
as: "step",
|
|
11774
|
+
type: "code",
|
|
11775
|
+
name: "Process",
|
|
11776
|
+
code: "export default ({value}) => ({result:value})"
|
|
11777
|
+
},
|
|
11778
|
+
{
|
|
11779
|
+
op: "edge.connect",
|
|
11780
|
+
source: "$start",
|
|
11781
|
+
target: "$step"
|
|
11782
|
+
},
|
|
11783
|
+
{
|
|
11784
|
+
op: "node.update",
|
|
11785
|
+
node: "$step",
|
|
11786
|
+
set: { description: "Created and connected in one atomic edit." }
|
|
11787
|
+
}
|
|
11788
|
+
]
|
|
11789
|
+
}, {
|
|
11790
|
+
baseRevision: "REVISION",
|
|
11791
|
+
requestId: "REQUEST",
|
|
11792
|
+
edits: [{
|
|
11793
|
+
op: "text.edit",
|
|
11794
|
+
node: "NODE",
|
|
11795
|
+
field: "prompt",
|
|
11796
|
+
oldText: "Original rule.",
|
|
11797
|
+
newText: "Updated rule."
|
|
11798
|
+
}]
|
|
11799
|
+
}]
|
|
11800
|
+
},
|
|
11801
|
+
check: {
|
|
11802
|
+
schema: authoringCheckSchema,
|
|
11803
|
+
guidance: "Check a fixed revision. In the CLI, pass this identity with --revision REVISION.",
|
|
11804
|
+
examples: [{ revisionId: "REVISION" }]
|
|
11805
|
+
}
|
|
11806
|
+
};
|
|
11807
|
+
/** Transport-independent discovery of the same requests the service validates. */
|
|
11808
|
+
function authoringRequestContract(name) {
|
|
11809
|
+
if (!Object.hasOwn(requestContracts, name)) return void 0;
|
|
11810
|
+
const contract = requestContracts[name];
|
|
11811
|
+
return {
|
|
11812
|
+
request: toJSONSchema(contract.schema, { io: "input" }),
|
|
11813
|
+
guidance: contract.guidance,
|
|
11814
|
+
examples: contract.examples
|
|
11815
|
+
};
|
|
11816
|
+
}
|
|
11817
|
+
function authoringSchema(kind) {
|
|
11818
|
+
return kind == null ? {
|
|
11819
|
+
types: authoringTypes,
|
|
11820
|
+
request: toJSONSchema(authoringRequestSchema),
|
|
11821
|
+
guidance: "Read a node type schema before creating or configuring it. Use $alias to reference a preceding node.add in the same batch. Read returns stable node references. Long code and prompt fields use text reads and edits. Changes use the observed baseRevision and a stable requestId."
|
|
11822
|
+
} : {
|
|
11823
|
+
type: kind,
|
|
11824
|
+
inputSources: ["poll", "integration"].includes(kind) ? [
|
|
11825
|
+
"value",
|
|
11826
|
+
"unset",
|
|
11827
|
+
"default"
|
|
11828
|
+
] : [
|
|
11829
|
+
"manual",
|
|
11830
|
+
"error",
|
|
11831
|
+
"cron",
|
|
11832
|
+
"webhook",
|
|
11833
|
+
"value",
|
|
11834
|
+
"condition"
|
|
11835
|
+
].includes(kind) ? [] : [
|
|
11836
|
+
"value",
|
|
11837
|
+
"unset",
|
|
11838
|
+
"default",
|
|
11839
|
+
"output",
|
|
11840
|
+
"variable",
|
|
11841
|
+
"sources"
|
|
11842
|
+
],
|
|
11843
|
+
extensibleInputs: [
|
|
11844
|
+
"code",
|
|
11845
|
+
"agent",
|
|
11846
|
+
"llm",
|
|
11847
|
+
"wait",
|
|
11848
|
+
"approval"
|
|
11849
|
+
].includes(kind),
|
|
11850
|
+
guidance: kind == "condition" ? "Edit branch operands through config.branches. A branch can test one expression, all expressions, or any alternatives. Unmatched execution uses branch otherwise." : ["poll", "integration"].includes(kind) ? "Configure static parameters with node.add.inputs or input.set. Definitions come from the selected Trigger key; execution output and variable sources are unavailable." : kind == "llm" ? "Configure model settings, message templates and history as defaults. Input bindings with the same names override these defaults; named business inputs can be bound directly. Template strings interpolate {{name}}." : kind == "openapi" ? "Select an operation; the tool resolves its ports and authentication. Read authenticationChoices from node details. authentication is replaced as a complete choice. Bind advertised credentials through inputs." : "Supply business configuration and input data. Fixed definitions are assembled by the tool. Existing constraints and defaults are preserved on partial updates.",
|
|
11851
|
+
example: {
|
|
11852
|
+
op: "node.add",
|
|
11853
|
+
as: "step",
|
|
11854
|
+
type: kind,
|
|
11855
|
+
name: "Step",
|
|
11856
|
+
...{
|
|
11857
|
+
connector: { config: {
|
|
11858
|
+
action: "<Action ID>",
|
|
11859
|
+
connectionId: "<Connection ID>"
|
|
11860
|
+
} },
|
|
11861
|
+
poll: { config: {
|
|
11862
|
+
key: "<Trigger key>",
|
|
11863
|
+
schedule: [{
|
|
11864
|
+
type: "every",
|
|
11865
|
+
unit: "minute",
|
|
11866
|
+
value: 5
|
|
11867
|
+
}]
|
|
11868
|
+
} },
|
|
11869
|
+
integration: { config: { key: "<Trigger key>" } },
|
|
11870
|
+
openapi: { config: {
|
|
11871
|
+
sourceUrl: "https://example.com/openapi.json",
|
|
11872
|
+
path: "/items",
|
|
11873
|
+
method: "get"
|
|
11874
|
+
} },
|
|
11875
|
+
code: {
|
|
11876
|
+
code: "export default ({value}) => ({result:value})",
|
|
11877
|
+
inputs: { value: {
|
|
11878
|
+
kind: "value",
|
|
11879
|
+
value: "Hello"
|
|
11880
|
+
} }
|
|
11881
|
+
},
|
|
11882
|
+
condition: { config: {
|
|
11883
|
+
match: "first",
|
|
11884
|
+
branches: [{
|
|
11885
|
+
name: "yes",
|
|
11886
|
+
when: {
|
|
11887
|
+
left: {
|
|
11888
|
+
kind: "value",
|
|
11889
|
+
value: 120
|
|
11890
|
+
},
|
|
11891
|
+
operator: ">",
|
|
11892
|
+
right: {
|
|
11893
|
+
kind: "value",
|
|
11894
|
+
value: 100
|
|
11895
|
+
}
|
|
11896
|
+
}
|
|
11897
|
+
}]
|
|
11898
|
+
} },
|
|
11899
|
+
value: { config: { values: {
|
|
11900
|
+
threshold: 100,
|
|
11901
|
+
region: "EU"
|
|
11902
|
+
} } },
|
|
11903
|
+
webhook: { config: {
|
|
11904
|
+
method: "POST",
|
|
11905
|
+
body: { orderId: {
|
|
11906
|
+
schema: { type: "string" },
|
|
11907
|
+
nullable: false
|
|
11908
|
+
} }
|
|
11909
|
+
} },
|
|
11910
|
+
wait: {
|
|
11911
|
+
prompt: "Continue processing this order?",
|
|
11912
|
+
inputs: { order: {
|
|
11913
|
+
kind: "value",
|
|
11914
|
+
value: { orderId: "A-1" }
|
|
11915
|
+
} }
|
|
11916
|
+
},
|
|
11917
|
+
approval: {
|
|
11918
|
+
prompt: "Approve this order?",
|
|
11919
|
+
inputs: { order: {
|
|
11920
|
+
kind: "value",
|
|
11921
|
+
value: { orderId: "A-1" }
|
|
11922
|
+
} }
|
|
11923
|
+
},
|
|
11924
|
+
llm: {
|
|
11925
|
+
config: {
|
|
11926
|
+
model: { model: "deepseek-v4-flash" },
|
|
11927
|
+
template: [{
|
|
11928
|
+
role: "user",
|
|
11929
|
+
content: "Summarize {{order}}."
|
|
11930
|
+
}]
|
|
11931
|
+
},
|
|
11932
|
+
inputs: { order: {
|
|
11933
|
+
kind: "value",
|
|
11934
|
+
value: {
|
|
11935
|
+
orderId: "A-1",
|
|
11936
|
+
total: 42
|
|
11937
|
+
}
|
|
11938
|
+
} }
|
|
11939
|
+
},
|
|
11940
|
+
agent: {
|
|
11941
|
+
config: { model: "deepseek-v4-flash" },
|
|
11942
|
+
inputs: { orders: {
|
|
11943
|
+
kind: "value",
|
|
11944
|
+
value: [{
|
|
11945
|
+
orderId: "A-1",
|
|
11946
|
+
total: 42
|
|
11947
|
+
}]
|
|
11948
|
+
} },
|
|
11949
|
+
prompt: "Summarize {{orders}}."
|
|
11950
|
+
}
|
|
11951
|
+
}[kind]
|
|
11952
|
+
},
|
|
11953
|
+
configuration: toJSONSchema(authoringConfigurations[kind].partial()),
|
|
11954
|
+
texts: kind == "code" ? ["code"] : [
|
|
11955
|
+
"agent",
|
|
11956
|
+
"wait",
|
|
11957
|
+
"approval"
|
|
11958
|
+
].includes(kind) ? ["prompt"] : []
|
|
11959
|
+
};
|
|
11960
|
+
}
|
|
11961
|
+
var authoringDiagnosticSchema = object$1({
|
|
11962
|
+
code: id$2,
|
|
11963
|
+
message: string(),
|
|
11964
|
+
nodes: array(id$2),
|
|
11965
|
+
field: string().optional(),
|
|
11966
|
+
line: number().optional(),
|
|
11967
|
+
column: number().optional()
|
|
11968
|
+
});
|
|
11969
|
+
var authoringCheckResponse = object$1({
|
|
11970
|
+
flowId: id$2,
|
|
11971
|
+
revisionId: id$2,
|
|
11972
|
+
valid: boolean(),
|
|
11973
|
+
diagnostics: array(authoringDiagnosticSchema),
|
|
11974
|
+
version: literal(1)
|
|
11975
|
+
});
|
|
11976
|
+
var authoringEditResponse = object$1({
|
|
11977
|
+
flowId: id$2,
|
|
11978
|
+
saved: literal(true),
|
|
11979
|
+
revision: id$2,
|
|
11980
|
+
nodes: record$3(id$2, id$2),
|
|
11981
|
+
changes: array(object$1({
|
|
11982
|
+
index: int(),
|
|
11983
|
+
op: id$2,
|
|
11984
|
+
node: id$2.optional()
|
|
11985
|
+
})),
|
|
11986
|
+
validation: object$1({
|
|
11987
|
+
status: _enum([
|
|
11988
|
+
"valid",
|
|
11989
|
+
"invalid",
|
|
11990
|
+
"unavailable"
|
|
11991
|
+
]),
|
|
11992
|
+
diagnostics: array(authoringDiagnosticSchema).optional()
|
|
11993
|
+
}),
|
|
11994
|
+
version: literal(1)
|
|
11995
|
+
});
|
|
11996
|
+
var authoringReadResponse = object$1({
|
|
11997
|
+
flowId: id$2,
|
|
11998
|
+
revision: id$2,
|
|
11999
|
+
data: object$1({
|
|
12000
|
+
nodes: array(record$3(string(), json$3)).optional(),
|
|
12001
|
+
edges: array(json$3).optional(),
|
|
12002
|
+
text: record$3(string(), json$3).optional()
|
|
12003
|
+
}),
|
|
12004
|
+
version: literal(1)
|
|
12005
|
+
});
|
|
12006
|
+
var authoringSearchResponse = object$1({
|
|
12007
|
+
flowId: id$2,
|
|
12008
|
+
revision: id$2,
|
|
12009
|
+
data: object$1({
|
|
12010
|
+
matches: array(object$1({
|
|
12011
|
+
node: id$2,
|
|
12012
|
+
field: id$2,
|
|
12013
|
+
line: int().optional(),
|
|
12014
|
+
excerpt: string()
|
|
12015
|
+
})),
|
|
12016
|
+
total: int(),
|
|
12017
|
+
nextOffset: int().optional()
|
|
12018
|
+
}),
|
|
12019
|
+
version: literal(1)
|
|
12020
|
+
});
|
|
12021
|
+
//#endregion
|
|
12022
|
+
//#region src/trigger/common/contract.ts
|
|
12023
|
+
var errorOutputs = [
|
|
12024
|
+
{
|
|
12025
|
+
handle: "workflow",
|
|
12026
|
+
nullable: false,
|
|
12027
|
+
jsonSchema: {
|
|
12028
|
+
type: "object",
|
|
12029
|
+
additionalProperties: false,
|
|
12030
|
+
required: [
|
|
12031
|
+
"flowId",
|
|
12032
|
+
"name",
|
|
12033
|
+
"revisionId",
|
|
12034
|
+
"publicationId"
|
|
12035
|
+
],
|
|
12036
|
+
properties: {
|
|
12037
|
+
flowId: { type: "string" },
|
|
12038
|
+
name: { type: "string" },
|
|
12039
|
+
revisionId: { type: "string" },
|
|
12040
|
+
publicationId: { type: ["string", "null"] }
|
|
12041
|
+
}
|
|
12042
|
+
}
|
|
12043
|
+
},
|
|
12044
|
+
{
|
|
12045
|
+
handle: "execution",
|
|
12046
|
+
nullable: false,
|
|
12047
|
+
jsonSchema: {
|
|
12048
|
+
type: "object",
|
|
12049
|
+
additionalProperties: false,
|
|
12050
|
+
required: [
|
|
12051
|
+
"runId",
|
|
12052
|
+
"status",
|
|
12053
|
+
"startedAt",
|
|
12054
|
+
"finishedAt"
|
|
12055
|
+
],
|
|
12056
|
+
properties: {
|
|
12057
|
+
runId: { type: "string" },
|
|
12058
|
+
status: { enum: ["failed", "indeterminate"] },
|
|
12059
|
+
startedAt: { type: ["string", "null"] },
|
|
12060
|
+
finishedAt: { type: "string" }
|
|
12061
|
+
}
|
|
12062
|
+
}
|
|
12063
|
+
},
|
|
12064
|
+
{
|
|
12065
|
+
handle: "error",
|
|
12066
|
+
nullable: false,
|
|
12067
|
+
jsonSchema: {
|
|
12068
|
+
type: "object",
|
|
12069
|
+
additionalProperties: false,
|
|
12070
|
+
required: ["code", "message"],
|
|
12071
|
+
properties: {
|
|
12072
|
+
code: { type: "string" },
|
|
12073
|
+
message: { type: "string" },
|
|
12074
|
+
nodeId: { type: "string" },
|
|
12075
|
+
jobId: { type: "string" },
|
|
12076
|
+
path: {
|
|
12077
|
+
type: "array",
|
|
12078
|
+
items: { type: "string" }
|
|
12079
|
+
}
|
|
12080
|
+
}
|
|
12081
|
+
}
|
|
12082
|
+
}
|
|
12083
|
+
];
|
|
12084
|
+
var webhookOutputs = [
|
|
12085
|
+
{
|
|
12086
|
+
handle: "headers",
|
|
12087
|
+
jsonSchema: {
|
|
12088
|
+
type: "object",
|
|
12089
|
+
additionalProperties: { type: "string" }
|
|
12090
|
+
},
|
|
12091
|
+
nullable: false
|
|
12092
|
+
},
|
|
12093
|
+
{
|
|
12094
|
+
handle: "query",
|
|
12095
|
+
jsonSchema: {
|
|
12096
|
+
type: "object",
|
|
12097
|
+
additionalProperties: {
|
|
12098
|
+
type: ["string", "array"],
|
|
12099
|
+
items: { type: "string" }
|
|
12100
|
+
}
|
|
12101
|
+
},
|
|
12102
|
+
nullable: false
|
|
12103
|
+
},
|
|
12104
|
+
{
|
|
12105
|
+
handle: "body",
|
|
12106
|
+
jsonSchema: {
|
|
12107
|
+
type: "object",
|
|
12108
|
+
additionalProperties: true
|
|
12109
|
+
},
|
|
12110
|
+
nullable: false
|
|
12111
|
+
},
|
|
12112
|
+
{
|
|
12113
|
+
handle: "webhookUrl",
|
|
12114
|
+
jsonSchema: { type: "string" },
|
|
12115
|
+
nullable: false
|
|
12116
|
+
}
|
|
12117
|
+
];
|
|
12118
|
+
var cronOutputs = [{
|
|
12119
|
+
handle: "scheduledAt",
|
|
12120
|
+
jsonSchema: {
|
|
12121
|
+
type: "string",
|
|
12122
|
+
format: "date-time"
|
|
12123
|
+
},
|
|
12124
|
+
nullable: false
|
|
12125
|
+
}];
|
|
12126
|
+
function triggerOutputDefinitions(trigger) {
|
|
12127
|
+
switch (trigger.kind) {
|
|
12128
|
+
case "error": return errorOutputs;
|
|
12129
|
+
case "manual": return [];
|
|
12130
|
+
case "cron": return cronOutputs;
|
|
12131
|
+
case "poll":
|
|
12132
|
+
case "integration": return trigger.definition.outputs;
|
|
12133
|
+
case "webhook": return webhookOutputs.filter((port) => port.handle !== "body" || webhookSupportsBody(trigger.method)).map((port) => port.handle === "body" ? Object.assign({}, port, { jsonSchema: {
|
|
12134
|
+
type: "object",
|
|
12135
|
+
additionalProperties: false,
|
|
12136
|
+
properties: Object.fromEntries(trigger.bodyFields.map((field) => [field.handle, field.jsonSchema])),
|
|
12137
|
+
required: trigger.bodyFields.filter((field) => !field.nullable && !Object.hasOwn(field, "value")).map((field) => field.handle)
|
|
12138
|
+
} }) : port);
|
|
12139
|
+
}
|
|
12140
|
+
}
|
|
12141
|
+
function triggerOutputPorts(trigger) {
|
|
12142
|
+
return Object.fromEntries(triggerOutputDefinitions(trigger).map(({ handle, ...port }) => [handle, port]));
|
|
12143
|
+
}
|
|
12144
|
+
//#endregion
|
|
12145
|
+
//#region src/flow/common/graph.ts
|
|
12146
|
+
function nodeInputPorts(node) {
|
|
12147
|
+
switch (node.kind) {
|
|
12148
|
+
case "condition": return conditionInputPorts(node);
|
|
12149
|
+
case "value": return {};
|
|
12150
|
+
case "task": return portsByHandle([...node.task.inputs, ...node.additionalInputs ?? []]);
|
|
12151
|
+
case "approval":
|
|
12152
|
+
case "wait": return portsByHandle(node.inputDefinitions);
|
|
12153
|
+
case "cron":
|
|
12154
|
+
case "integration":
|
|
12155
|
+
case "poll":
|
|
12156
|
+
case "error":
|
|
12157
|
+
case "manual":
|
|
12158
|
+
case "webhook": return {};
|
|
12159
|
+
}
|
|
12160
|
+
}
|
|
12161
|
+
function resolutionActions(node) {
|
|
12162
|
+
return node.kind == "wait" ? ["continue"] : ["approve", "reject"];
|
|
12163
|
+
}
|
|
12164
|
+
var objectPort = (properties) => ({
|
|
12165
|
+
nullable: false,
|
|
12166
|
+
jsonSchema: {
|
|
12167
|
+
type: "object",
|
|
12168
|
+
properties,
|
|
12169
|
+
required: Object.keys(properties),
|
|
12170
|
+
additionalProperties: false
|
|
12171
|
+
}
|
|
12172
|
+
});
|
|
12173
|
+
function resolutionOutputPorts(node) {
|
|
12174
|
+
const actions = resolutionActions(node);
|
|
12175
|
+
const inputs = {
|
|
12176
|
+
type: "object",
|
|
12177
|
+
properties: Object.fromEntries(node.inputDefinitions.map((port) => [port.handle, {}])),
|
|
12178
|
+
required: node.inputDefinitions.map((port) => port.handle),
|
|
12179
|
+
additionalProperties: false
|
|
12180
|
+
};
|
|
12181
|
+
return {
|
|
12182
|
+
pending: objectPort({
|
|
12183
|
+
inputs,
|
|
12184
|
+
prompt: { type: "string" },
|
|
12185
|
+
...Object.fromEntries(actions.map((action) => [`${action}Url`, { type: "string" }])),
|
|
12186
|
+
expiresAt: { type: "string" }
|
|
12187
|
+
}),
|
|
12188
|
+
...Object.fromEntries(actions.map((action) => [action, objectPort({
|
|
12189
|
+
inputs,
|
|
12190
|
+
action: { const: action },
|
|
12191
|
+
resolvedAt: { type: "string" },
|
|
12192
|
+
comment: { type: ["string", "null"] }
|
|
12193
|
+
})]))
|
|
12194
|
+
};
|
|
12195
|
+
}
|
|
12196
|
+
function nodeOutputPorts(node) {
|
|
12197
|
+
switch (node.kind) {
|
|
12198
|
+
case "condition": return {};
|
|
12199
|
+
case "value": return portsByHandle(node.values);
|
|
12200
|
+
case "task": return portsByHandle(node.task.outputs);
|
|
12201
|
+
case "approval":
|
|
12202
|
+
case "wait": return resolutionOutputPorts(node);
|
|
12203
|
+
case "cron":
|
|
12204
|
+
case "integration":
|
|
12205
|
+
case "poll":
|
|
12206
|
+
case "error":
|
|
12207
|
+
case "manual":
|
|
12208
|
+
case "webhook": return triggerOutputPorts(node);
|
|
12209
|
+
}
|
|
12210
|
+
}
|
|
12211
|
+
//#endregion
|
|
12212
|
+
//#region src/flow/common/moduleChanges.ts
|
|
12213
|
+
async function imports(source) {
|
|
12214
|
+
try {
|
|
12215
|
+
const { parse } = await import("./lib-DrKav3HG.js");
|
|
12216
|
+
const program = parse(source, {
|
|
12217
|
+
errorRecovery: true,
|
|
12218
|
+
sourceType: "module"
|
|
12219
|
+
}).program;
|
|
12220
|
+
const dependencies = /* @__PURE__ */ new Set();
|
|
12221
|
+
for (const statement of program.body) {
|
|
12222
|
+
if (statement.type != "ImportDeclaration") continue;
|
|
12223
|
+
const match = /^\.\/(.+)\.mjs$/.exec(statement.source.value);
|
|
12224
|
+
if (match?.[1] != null) dependencies.add(match[1]);
|
|
12225
|
+
}
|
|
12226
|
+
return [...dependencies].toSorted();
|
|
12227
|
+
} catch {
|
|
12228
|
+
return [];
|
|
12229
|
+
}
|
|
12230
|
+
}
|
|
12231
|
+
//#endregion
|
|
12232
|
+
//#region src/flow/common/nodeChanges.ts
|
|
12233
|
+
var codeTaskTemplate = `export default async function (inputs, context) {
|
|
12234
|
+
return { result: inputs.value }
|
|
12235
|
+
}
|
|
12236
|
+
`;
|
|
12237
|
+
var defaultCodeTaskPorts = {
|
|
12238
|
+
inputs: [{
|
|
12239
|
+
handle: "value",
|
|
12240
|
+
jsonSchema: { type: "string" },
|
|
12241
|
+
nullable: true,
|
|
12242
|
+
value: "foo"
|
|
12243
|
+
}],
|
|
12244
|
+
outputs: [{
|
|
12245
|
+
handle: "result",
|
|
12246
|
+
jsonSchema: {},
|
|
12247
|
+
nullable: true
|
|
12248
|
+
}]
|
|
12249
|
+
};
|
|
12250
|
+
function createCodeTask(identity, name, module = void 0, ports = defaultCodeTaskPorts) {
|
|
12251
|
+
return [{
|
|
12252
|
+
kind: "module.create",
|
|
12253
|
+
module: {
|
|
12254
|
+
...module ?? {
|
|
12255
|
+
imports: [],
|
|
12256
|
+
source: codeTaskTemplate
|
|
12257
|
+
},
|
|
12258
|
+
name
|
|
12259
|
+
},
|
|
12260
|
+
moduleId: identity.moduleId
|
|
12261
|
+
}, {
|
|
12262
|
+
kind: "graph.node.create",
|
|
12263
|
+
node: {
|
|
12264
|
+
inputs: defaultInputs(ports.inputs),
|
|
12265
|
+
kind: "task",
|
|
12266
|
+
name,
|
|
12267
|
+
task: {
|
|
12268
|
+
capabilities: ports.capabilities ?? [{
|
|
12269
|
+
kind: "connector",
|
|
12270
|
+
mode: "independent",
|
|
12271
|
+
actions: []
|
|
12272
|
+
}],
|
|
12273
|
+
inputs: ports.inputs,
|
|
12274
|
+
moduleId: identity.moduleId,
|
|
12275
|
+
name,
|
|
12276
|
+
outputs: ports.outputs
|
|
12277
|
+
}
|
|
12278
|
+
},
|
|
12279
|
+
nodeId: identity.nodeId
|
|
12280
|
+
}];
|
|
12281
|
+
}
|
|
12282
|
+
function createManagedTask(identity, task) {
|
|
12283
|
+
return [{
|
|
12284
|
+
kind: "graph.node.create",
|
|
12285
|
+
node: {
|
|
12286
|
+
inputs: defaultInputs(task.inputs),
|
|
12287
|
+
kind: "task",
|
|
12288
|
+
name: task.name,
|
|
12289
|
+
task
|
|
12290
|
+
},
|
|
12291
|
+
nodeId: identity.nodeId
|
|
12292
|
+
}];
|
|
12293
|
+
}
|
|
12294
|
+
function createAgentTask(identity, name, defaults = {}) {
|
|
12295
|
+
return createManagedTask(identity, {
|
|
12296
|
+
name,
|
|
12297
|
+
inputs: defaults.inputs ?? [{
|
|
12298
|
+
handle: "input",
|
|
12299
|
+
jsonSchema: { type: "string" },
|
|
12300
|
+
nullable: false,
|
|
12301
|
+
value: ""
|
|
12302
|
+
}],
|
|
12303
|
+
outputs: [{
|
|
12304
|
+
handle: "output",
|
|
12305
|
+
jsonSchema: { type: "string" },
|
|
12306
|
+
nullable: false,
|
|
12307
|
+
description: defaults.outputDescription ?? "The final result produced by the Agent."
|
|
12308
|
+
}],
|
|
12309
|
+
executor: {
|
|
12310
|
+
kind: "agent",
|
|
12311
|
+
model: "deepseek-v4-flash",
|
|
12312
|
+
prompt: defaults.prompt ?? "Summarize the following content, highlighting key points and next steps.\n\n{{input}}",
|
|
12313
|
+
maxRounds: 10,
|
|
12314
|
+
tools: []
|
|
12315
|
+
}
|
|
12316
|
+
});
|
|
12317
|
+
}
|
|
12318
|
+
function createLlmTask(identity, name, mode, outputDescription, options = {}) {
|
|
12319
|
+
const values = options.inputs ?? {};
|
|
12320
|
+
return createManagedTask(identity, {
|
|
12321
|
+
executor: {
|
|
12322
|
+
kind: "llm",
|
|
12323
|
+
mode
|
|
12324
|
+
},
|
|
12325
|
+
inputs: [
|
|
12326
|
+
{
|
|
12327
|
+
handle: "messages",
|
|
12328
|
+
jsonSchema: {
|
|
12329
|
+
items: { type: "object" },
|
|
12330
|
+
type: "array"
|
|
12331
|
+
},
|
|
12332
|
+
nullable: true,
|
|
12333
|
+
value: llmInputValue(values, "messages", null)
|
|
12334
|
+
},
|
|
12335
|
+
{
|
|
12336
|
+
handle: "input",
|
|
12337
|
+
jsonSchema: { type: "string" },
|
|
12338
|
+
nullable: false,
|
|
12339
|
+
value: llmInputValue(values, "input", "Alex")
|
|
12340
|
+
},
|
|
12341
|
+
{
|
|
12342
|
+
handle: "template",
|
|
12343
|
+
jsonSchema: {
|
|
12344
|
+
items: { type: "object" },
|
|
12345
|
+
minItems: 1,
|
|
12346
|
+
type: "array"
|
|
12347
|
+
},
|
|
12348
|
+
nullable: false,
|
|
12349
|
+
value: llmInputValue(values, "template", [{
|
|
12350
|
+
content: "Hello, I'm {{input}}",
|
|
12351
|
+
role: "user"
|
|
12352
|
+
}])
|
|
12353
|
+
},
|
|
12354
|
+
{
|
|
12355
|
+
handle: "model",
|
|
12356
|
+
jsonSchema: { type: "object" },
|
|
12357
|
+
nullable: false,
|
|
12358
|
+
value: llmInputValue(values, "model", { model: "deepseek-v4-flash" })
|
|
12359
|
+
}
|
|
12360
|
+
],
|
|
12361
|
+
name,
|
|
12362
|
+
outputs: [{
|
|
12363
|
+
...options.output,
|
|
12364
|
+
description: options.output?.description ?? outputDescription,
|
|
12365
|
+
handle: "output",
|
|
12366
|
+
jsonSchema: options.output?.jsonSchema ?? (mode == "chat" ? { type: "string" } : {}),
|
|
12367
|
+
nullable: options.output?.nullable ?? false
|
|
12368
|
+
}]
|
|
12369
|
+
});
|
|
12370
|
+
}
|
|
12371
|
+
function createCondition(nodeId, name) {
|
|
12372
|
+
return [{
|
|
12373
|
+
kind: "graph.node.create",
|
|
12374
|
+
node: {
|
|
12375
|
+
cases: [{
|
|
12376
|
+
groups: [{ expressions: [{
|
|
12377
|
+
left: { kind: "value" },
|
|
12378
|
+
operator: "==",
|
|
12379
|
+
right: { kind: "value" }
|
|
12380
|
+
}] }],
|
|
12381
|
+
output: "case"
|
|
12382
|
+
}],
|
|
12383
|
+
matchMode: "first",
|
|
12384
|
+
inputs: {},
|
|
12385
|
+
kind: "condition",
|
|
12386
|
+
name
|
|
12387
|
+
},
|
|
12388
|
+
nodeId
|
|
12389
|
+
}];
|
|
12390
|
+
}
|
|
12391
|
+
function createValue(nodeId, name, values = [{
|
|
12392
|
+
handle: "value",
|
|
12393
|
+
jsonSchema: {},
|
|
12394
|
+
nullable: true,
|
|
12395
|
+
value: null
|
|
12396
|
+
}]) {
|
|
12397
|
+
return [{
|
|
12398
|
+
kind: "graph.node.create",
|
|
12399
|
+
node: {
|
|
12400
|
+
inputs: {},
|
|
12401
|
+
kind: "value",
|
|
12402
|
+
name,
|
|
12403
|
+
values
|
|
12404
|
+
},
|
|
12405
|
+
nodeId
|
|
12406
|
+
}];
|
|
12407
|
+
}
|
|
12408
|
+
function createWait(nodeId, name) {
|
|
12409
|
+
return [{
|
|
12410
|
+
kind: "graph.node.create",
|
|
12411
|
+
node: {
|
|
12412
|
+
inputDefinitions: [],
|
|
12413
|
+
inputs: {},
|
|
12414
|
+
kind: "wait",
|
|
12415
|
+
name,
|
|
12416
|
+
prompt: name
|
|
12417
|
+
},
|
|
12418
|
+
nodeId
|
|
12419
|
+
}];
|
|
12420
|
+
}
|
|
12421
|
+
function createApproval(nodeId, name) {
|
|
12422
|
+
return [{
|
|
12423
|
+
kind: "graph.node.create",
|
|
12424
|
+
node: {
|
|
12425
|
+
inputDefinitions: [],
|
|
12426
|
+
inputs: {},
|
|
12427
|
+
kind: "approval",
|
|
12428
|
+
name,
|
|
12429
|
+
prompt: name
|
|
12430
|
+
},
|
|
12431
|
+
nodeId
|
|
12432
|
+
}];
|
|
12433
|
+
}
|
|
12434
|
+
function createBuiltinTrigger(nodeId, node) {
|
|
12435
|
+
return [{
|
|
12436
|
+
kind: "graph.node.create",
|
|
12437
|
+
node,
|
|
12438
|
+
nodeId
|
|
12439
|
+
}];
|
|
12440
|
+
}
|
|
12441
|
+
function createProviderTrigger(nodeId, definition, options) {
|
|
12442
|
+
const name = options.name ?? definition.displayName;
|
|
12443
|
+
return [{
|
|
12444
|
+
kind: "graph.node.create",
|
|
12445
|
+
node: definition.type == "poll" ? {
|
|
12446
|
+
...options.connectionId == null ? {} : { connectionId: options.connectionId },
|
|
12447
|
+
config: inputValues(options.config),
|
|
12448
|
+
definition,
|
|
12449
|
+
kind: "poll",
|
|
12450
|
+
name,
|
|
12451
|
+
pollTimes: options.schedule ?? [{
|
|
12452
|
+
type: "every",
|
|
12453
|
+
unit: "minute",
|
|
12454
|
+
value: 5
|
|
12455
|
+
}]
|
|
12456
|
+
} : {
|
|
12457
|
+
...options.connectionId == null ? {} : { connectionId: options.connectionId },
|
|
12458
|
+
config: inputValues(options.config),
|
|
12459
|
+
definition,
|
|
12460
|
+
kind: "integration",
|
|
12461
|
+
name
|
|
12462
|
+
},
|
|
12463
|
+
nodeId
|
|
12464
|
+
}];
|
|
12465
|
+
}
|
|
12466
|
+
function cleanVariableBindings(content, operations) {
|
|
12467
|
+
const before = bindingReferences(content.document);
|
|
12468
|
+
const changed = applyFlowChanges(content, operations);
|
|
12469
|
+
const after = bindingReferences(changed.document);
|
|
12470
|
+
return [...operations, ...[...before.keys()].flatMap((bindingId) => after.has(bindingId) || changed.document.bindings[bindingId]?.kind != "variable" ? [] : [{
|
|
12471
|
+
bindingId,
|
|
12472
|
+
kind: "binding.delete"
|
|
12473
|
+
}])];
|
|
12474
|
+
}
|
|
12475
|
+
function bindingReferences(document) {
|
|
12476
|
+
const references = /* @__PURE__ */ new Map();
|
|
12477
|
+
const add = (bindingId) => {
|
|
12478
|
+
references.set(bindingId, (references.get(bindingId) ?? 0) + 1);
|
|
12479
|
+
};
|
|
12480
|
+
for (const node of Object.values(document.graph.nodes)) {
|
|
12481
|
+
if (!("inputs" in node)) continue;
|
|
12482
|
+
const inputs = Object.values(nodeInputMappings(node));
|
|
12483
|
+
for (const mapping of inputs) {
|
|
12484
|
+
if (mapping.kind != "sources") continue;
|
|
12485
|
+
for (const source of mapping.sources) if (source.kind == "binding") add(source.bindingId);
|
|
12486
|
+
}
|
|
12487
|
+
}
|
|
12488
|
+
return references;
|
|
12489
|
+
}
|
|
12490
|
+
function defaultInputs(ports) {
|
|
12491
|
+
return Object.fromEntries(ports.flatMap((port) => "handle" in port && Object.hasOwn(port, "value") ? [[port.handle, {
|
|
12492
|
+
kind: "value",
|
|
12493
|
+
value: port.value
|
|
12494
|
+
}]] : []));
|
|
12495
|
+
}
|
|
12496
|
+
function llmInputValue(values, handle, fallback) {
|
|
12497
|
+
return values != null && Object.hasOwn(values, handle) ? values[handle] : fallback;
|
|
12498
|
+
}
|
|
12499
|
+
function createDecisionTask(identity, name = "AI Decision", questions) {
|
|
12500
|
+
return createManagedTask(identity, decisionTask(questions, name));
|
|
12501
|
+
}
|
|
12502
|
+
//#endregion
|
|
12503
|
+
//#region src/control/common/authoringCondition.ts
|
|
12504
|
+
/** Preserve empty groups in invalid drafts; do not turn them into unconditional branches. */
|
|
12505
|
+
function conditionConfigurationView(node, source) {
|
|
12506
|
+
const operand = (value) => value.kind == "source" ? source(value.source) : {
|
|
12507
|
+
kind: "value",
|
|
12508
|
+
...value.value === void 0 ? {} : { value: value.value },
|
|
12509
|
+
...value.jsonSchema === void 0 ? {} : { schema: value.jsonSchema }
|
|
12510
|
+
};
|
|
12511
|
+
const expression = (value) => ({
|
|
12512
|
+
left: operand(value.left),
|
|
12513
|
+
operator: value.operator,
|
|
12514
|
+
...value.right === void 0 ? {} : { right: operand(value.right) }
|
|
12515
|
+
});
|
|
12516
|
+
return {
|
|
12517
|
+
match: node.matchMode,
|
|
12518
|
+
branches: node.cases.map((branch) => {
|
|
12519
|
+
const groups = branch.groups.map((group) => group.expressions.length == 1 ? expression(group.expressions[0]) : { all: group.expressions.map(expression) });
|
|
12520
|
+
return {
|
|
12521
|
+
name: branch.output,
|
|
12522
|
+
...branch.description === void 0 ? {} : { description: branch.description },
|
|
12523
|
+
when: groups.length == 1 ? groups[0] : { any: groups }
|
|
12524
|
+
};
|
|
12525
|
+
})
|
|
12526
|
+
};
|
|
12527
|
+
}
|
|
12528
|
+
function prepareConditionConfiguration(config, source) {
|
|
12529
|
+
const operand = (value) => value.kind == "value" ? {
|
|
12530
|
+
kind: "value",
|
|
12531
|
+
...value.value === void 0 ? {} : { value: value.value },
|
|
12532
|
+
...value.schema === void 0 ? {} : { jsonSchema: value.schema }
|
|
12533
|
+
} : {
|
|
12534
|
+
kind: "source",
|
|
12535
|
+
source: source(value)
|
|
12536
|
+
};
|
|
12537
|
+
const expression = (value) => ({
|
|
12538
|
+
left: operand(value.left),
|
|
12539
|
+
operator: value.operator,
|
|
12540
|
+
...value.right === void 0 ? {} : { right: operand(value.right) }
|
|
12541
|
+
});
|
|
12542
|
+
return {
|
|
12543
|
+
matchMode: config.match,
|
|
12544
|
+
cases: config.branches.map((branch) => {
|
|
12545
|
+
const groups = "any" in branch.when ? branch.when.any : [branch.when];
|
|
12546
|
+
return {
|
|
12547
|
+
output: branch.name,
|
|
12548
|
+
...branch.description === void 0 ? {} : { description: branch.description },
|
|
12549
|
+
groups: groups.map((group) => ({ expressions: ("all" in group ? group.all : [group]).map(expression) }))
|
|
12550
|
+
};
|
|
12551
|
+
})
|
|
12552
|
+
};
|
|
12553
|
+
}
|
|
12554
|
+
/** Map a path relative to a persisted Condition configuration into its normalized public config. */
|
|
12555
|
+
function conditionConfigurationFieldPath(node, path) {
|
|
12556
|
+
if (path[0] == "matchMode") return ["match", ...path.slice(1)];
|
|
12557
|
+
if (path[0] != "cases") return path;
|
|
12558
|
+
if (path.length == 1) return ["branches"];
|
|
12559
|
+
const branchIndex = Number(path[1]), branch = node.cases[branchIndex], base = ["branches", path[1]];
|
|
12560
|
+
if (path[2] == "output") return [
|
|
12561
|
+
...base,
|
|
12562
|
+
"name",
|
|
12563
|
+
...path.slice(3)
|
|
12564
|
+
];
|
|
12565
|
+
if (path[2] != "groups") return [...base, ...path.slice(2)];
|
|
12566
|
+
base.push("when");
|
|
12567
|
+
if (branch == null || path.length == 3) return base;
|
|
12568
|
+
const groupIndex = Number(path[3]), group = branch.groups[groupIndex];
|
|
12569
|
+
if (branch.groups.length != 1) base.push("any", path[3]);
|
|
12570
|
+
if (path[4] != "expressions") return [...base, ...path.slice(4)];
|
|
12571
|
+
if (group == null || path.length == 5) return group?.expressions.length == 1 ? base : [...base, "all"];
|
|
12572
|
+
if (group.expressions.length != 1) base.push("all", path[5]);
|
|
12573
|
+
const remaining = path.slice(6).filter((part, index) => !(index == 1 && part == "source"));
|
|
12574
|
+
if (remaining[0] == "left" || remaining[0] == "right") switch (remaining[1]) {
|
|
12575
|
+
case "jsonSchema":
|
|
12576
|
+
remaining[1] = "schema";
|
|
12577
|
+
break;
|
|
12578
|
+
case "nodeId":
|
|
12579
|
+
remaining[1] = "node";
|
|
12580
|
+
break;
|
|
12581
|
+
case "output":
|
|
12582
|
+
remaining[1] = "port";
|
|
12583
|
+
break;
|
|
12584
|
+
case "bindingId": remaining[1] = "name";
|
|
12585
|
+
}
|
|
12586
|
+
return [...base, ...remaining];
|
|
12587
|
+
}
|
|
12588
|
+
//#endregion
|
|
12589
|
+
//#region src/control/common/authoringDiagnosticFields.ts
|
|
12590
|
+
var metadata = /* @__PURE__ */ new Set([
|
|
12591
|
+
"name",
|
|
12592
|
+
"description",
|
|
12593
|
+
"icon",
|
|
12594
|
+
"timeoutMs",
|
|
12595
|
+
"maxExecutions"
|
|
12596
|
+
]);
|
|
12597
|
+
function portField(ports, path, parent) {
|
|
12598
|
+
const port = ports[Number(path[0])];
|
|
12599
|
+
if (port == null || !("handle" in port)) return parent;
|
|
12600
|
+
const field = `${parent}.${port.handle}`;
|
|
12601
|
+
switch (path[1]) {
|
|
12602
|
+
case "jsonSchema": return [
|
|
12603
|
+
field,
|
|
12604
|
+
"schema",
|
|
12605
|
+
...path.slice(2)
|
|
12606
|
+
].join(".");
|
|
12607
|
+
case "value": return [
|
|
12608
|
+
field,
|
|
12609
|
+
"default",
|
|
12610
|
+
...path.slice(2)
|
|
12611
|
+
].join(".");
|
|
12612
|
+
case "nullable":
|
|
12613
|
+
case "description": return [field, ...path.slice(1)].join(".");
|
|
12614
|
+
default: return field;
|
|
12615
|
+
}
|
|
12616
|
+
}
|
|
12617
|
+
/** Accept a decoded JSON Pointer, including or omitting its initial empty component. */
|
|
12618
|
+
function authoringDiagnosticField(_content, node, parts) {
|
|
12619
|
+
const path = parts[0] == "" ? parts.slice(1) : parts;
|
|
12620
|
+
if (path[0] == "modules") return "code";
|
|
12621
|
+
let location = path[0] == "document" && path[1] == "graph" && path[2] == "nodes" ? path.slice(4) : path;
|
|
12622
|
+
const inlineDefinition = node.kind == "task" && location[0] == "task";
|
|
12623
|
+
if (inlineDefinition) location = location.slice(1);
|
|
12624
|
+
if (location.length == 0) return "config";
|
|
12625
|
+
const head = location[0];
|
|
12626
|
+
if (!inlineDefinition && metadata.has(head)) return location.join(".");
|
|
12627
|
+
if (head == "prompt") return "prompt";
|
|
12628
|
+
if (head == "inputs" && !inlineDefinition) {
|
|
12629
|
+
if (node.kind == "condition" && location[1] != null) {
|
|
12630
|
+
const [branch, group, expression, side] = location[1].split("/");
|
|
12631
|
+
if (branch != null && group != null && expression != null && (side == "left" || side == "right")) return ["config", ...conditionConfigurationFieldPath(node, [
|
|
12632
|
+
"cases",
|
|
12633
|
+
branch,
|
|
12634
|
+
"groups",
|
|
12635
|
+
group,
|
|
12636
|
+
"expressions",
|
|
12637
|
+
expression,
|
|
12638
|
+
side
|
|
12639
|
+
])].join(".");
|
|
12640
|
+
return "config.branches";
|
|
12641
|
+
}
|
|
12642
|
+
return location[1] == null ? "inputs" : `inputs.${location[1]}`;
|
|
12643
|
+
}
|
|
12644
|
+
if (node.kind == "task") {
|
|
12645
|
+
const task = node.task;
|
|
12646
|
+
if (task == null) return "config";
|
|
12647
|
+
const executor = "executor" in task ? task.executor : void 0;
|
|
12648
|
+
if (head == "additionalInputs") return portField(node.additionalInputs ?? [], location.slice(1), "config.inputs");
|
|
12649
|
+
if (head == "inputs" || head == "outputs") {
|
|
12650
|
+
const ports = task[head];
|
|
12651
|
+
const port = ports[Number(location[1])];
|
|
12652
|
+
if (head == "outputs" && (executor?.kind == "agent" || executor?.kind == "llm")) return location[2] == "jsonSchema" ? [
|
|
12653
|
+
"config",
|
|
12654
|
+
"resultSchema",
|
|
12655
|
+
...location.slice(3)
|
|
12656
|
+
].join(".") : "config.resultSchema";
|
|
12657
|
+
if (head == "inputs" && executor?.kind == "llm" && port != null && "handle" in port && [
|
|
12658
|
+
"model",
|
|
12659
|
+
"template",
|
|
12660
|
+
"messages"
|
|
12661
|
+
].includes(port.handle)) return [
|
|
12662
|
+
"config",
|
|
12663
|
+
port.handle,
|
|
12664
|
+
...location[2] == "value" ? location.slice(3) : []
|
|
12665
|
+
].join(".");
|
|
12666
|
+
const custom = executor == null || executor.kind == "agent" || executor.kind == "llm";
|
|
12667
|
+
return portField(ports, location.slice(1), custom ? `config.${head}` : head == "inputs" ? "inputPorts" : "outputPorts");
|
|
12668
|
+
}
|
|
12669
|
+
if (head == "executor") {
|
|
12670
|
+
const field = location[1];
|
|
12671
|
+
if (field == null || field == "kind") return "config";
|
|
12672
|
+
if (field == "prompt") return "prompt";
|
|
12673
|
+
if (executor?.kind == "openapi") {
|
|
12674
|
+
if (field == "document") return "config";
|
|
12675
|
+
if (field == "auth") return "config.authentication";
|
|
12676
|
+
}
|
|
12677
|
+
if (executor?.kind == "agent") {
|
|
12678
|
+
if (field == "tools") {
|
|
12679
|
+
const tool = executor.tools[Number(location[2])];
|
|
12680
|
+
if (tool == null) return "config.tools";
|
|
12681
|
+
const base = `config.tools.${location[2]}`;
|
|
12682
|
+
if (location[3] == "id") return base;
|
|
12683
|
+
if (location[3] == "inputs") {
|
|
12684
|
+
const input = tool.inputs[Number(location[4])];
|
|
12685
|
+
if (input == null) return `${base}.inputs`;
|
|
12686
|
+
return location[5] == "source" ? [
|
|
12687
|
+
base,
|
|
12688
|
+
"inputs",
|
|
12689
|
+
input.handle,
|
|
12690
|
+
...location.slice(6)
|
|
12691
|
+
].join(".") : `${base}.inputs.${input.handle}`;
|
|
12692
|
+
}
|
|
12693
|
+
}
|
|
12694
|
+
if (field == "notification" && location[2] == "inputDefinitions") return "config.notification.inputs";
|
|
12695
|
+
}
|
|
12696
|
+
return ["config", ...location.slice(1)].join(".");
|
|
12697
|
+
}
|
|
12698
|
+
if (head == "capabilities") return ["config", ...location].join(".");
|
|
12699
|
+
if (head == "name") return "name";
|
|
12700
|
+
return "config";
|
|
12701
|
+
}
|
|
12702
|
+
switch (node.kind) {
|
|
12703
|
+
case "condition": return head == "cases" || head == "matchMode" ? ["config", ...conditionConfigurationFieldPath(node, location)].join(".") : "config";
|
|
12704
|
+
case "wait":
|
|
12705
|
+
case "approval": return head == "inputDefinitions" ? portField(node.inputDefinitions, location.slice(1), "config.inputs") : "config";
|
|
12706
|
+
case "webhook":
|
|
12707
|
+
if (head == "bodyFields") return portField(node.bodyFields, location.slice(1), "config.body");
|
|
12708
|
+
return head == "method" || head == "options" ? ["config", ...location].join(".") : "config";
|
|
12709
|
+
case "value": {
|
|
12710
|
+
if (head != "values") return "config";
|
|
12711
|
+
const port = node.values[Number(location[1])];
|
|
12712
|
+
if (port == null) return "config.values";
|
|
12713
|
+
if (location[2] == "value") return [
|
|
12714
|
+
"config",
|
|
12715
|
+
"values",
|
|
12716
|
+
port.handle,
|
|
12717
|
+
...location.slice(3)
|
|
12718
|
+
].join(".");
|
|
12719
|
+
return portField(node.values, location.slice(1), "config.outputs");
|
|
12720
|
+
}
|
|
12721
|
+
case "cron": return head == "cronTimes" ? [
|
|
12722
|
+
"config",
|
|
12723
|
+
"schedule",
|
|
12724
|
+
...location.slice(1)
|
|
12725
|
+
].join(".") : "config";
|
|
12726
|
+
case "poll":
|
|
12727
|
+
case "integration":
|
|
12728
|
+
if (head == "config") return location[1] == null ? "inputs" : `inputs.${location[1]}`;
|
|
12729
|
+
if (head == "definition") return location[1] == "configInputs" ? portField(node.definition.configInputs, location.slice(2), "inputPorts") : "config.key";
|
|
12730
|
+
if (head == "pollTimes") return [
|
|
12731
|
+
"config",
|
|
12732
|
+
"schedule",
|
|
12733
|
+
...location.slice(1)
|
|
12734
|
+
].join(".");
|
|
12735
|
+
return head == "connectionId" ? "config.connectionId" : "config";
|
|
12736
|
+
case "error": return head == "sourceFlowIds" ? ["config", ...location].join(".") : "config";
|
|
12737
|
+
default: return "config";
|
|
12738
|
+
}
|
|
12739
|
+
}
|
|
12740
|
+
//#endregion
|
|
12741
|
+
//#region src/control/common/authoringFields.ts
|
|
12742
|
+
var record$1 = (value) => value != null && typeof value == "object" && !Array.isArray(value) ? value : {};
|
|
12743
|
+
/** Business field contracts, independent of storage handles and presentation groups. */
|
|
12744
|
+
function fieldsView(ports) {
|
|
12745
|
+
return Object.fromEntries(ports.flatMap((port) => "handle" in port ? [[port.handle, {
|
|
12746
|
+
schema: port.jsonSchema,
|
|
12747
|
+
nullable: port.nullable,
|
|
12748
|
+
...port.description == null ? {} : { description: port.description },
|
|
12749
|
+
...Object.hasOwn(port, "value") ? { default: port.value } : {}
|
|
12750
|
+
}]] : []));
|
|
12751
|
+
}
|
|
12752
|
+
function fieldsToPorts(fields, previous) {
|
|
12753
|
+
const remaining = new Map(Object.entries(record$1(fields)));
|
|
12754
|
+
function port(handle, value) {
|
|
12755
|
+
const field = record$1(value);
|
|
12756
|
+
return {
|
|
12757
|
+
handle,
|
|
12758
|
+
jsonSchema: Object.hasOwn(field, "schema") ? field.schema : {},
|
|
12759
|
+
nullable: field.nullable ?? true,
|
|
12760
|
+
...field.description == null ? {} : { description: String(field.description) },
|
|
12761
|
+
...Object.hasOwn(field, "default") ? { value: field.default } : {}
|
|
12762
|
+
};
|
|
12763
|
+
}
|
|
12764
|
+
return [...previous.flatMap((old) => {
|
|
12765
|
+
if (!("handle" in old)) return [old];
|
|
12766
|
+
if (!remaining.has(old.handle)) return [];
|
|
12767
|
+
const value = remaining.get(old.handle);
|
|
12768
|
+
remaining.delete(old.handle);
|
|
12769
|
+
return [dequal(fieldsView([old])[old.handle], value) ? old : port(old.handle, value)];
|
|
12770
|
+
}), ...Array.from(remaining, ([handle, value]) => port(handle, value))];
|
|
12771
|
+
}
|
|
12772
|
+
//#endregion
|
|
12773
|
+
//#region src/control/common/authoringTools.ts
|
|
12774
|
+
var AuthoringToolInputError = class extends Error {
|
|
12775
|
+
constructor(details) {
|
|
12776
|
+
super(`Unknown input ${JSON.stringify(details.input)} for tool ${JSON.stringify(details.tool)}. Choose from: ${details.choices.join(", ") || "(none)"}.`);
|
|
12777
|
+
this.code = "tool.input-not-found";
|
|
12778
|
+
this.name = "AuthoringToolInputError";
|
|
12779
|
+
this.details = details;
|
|
12780
|
+
}
|
|
12781
|
+
};
|
|
12782
|
+
function outwardAgentTools(tools) {
|
|
12783
|
+
return tools.map(({ id: _id, inputs, ...tool }) => ({
|
|
12784
|
+
...tool,
|
|
12785
|
+
inputs: Object.fromEntries(inputs.map((input) => [input.handle, input.source]))
|
|
12786
|
+
}));
|
|
12787
|
+
}
|
|
12788
|
+
/** Keep persisted Action contracts until the caller selects a different Action. */
|
|
12789
|
+
async function prepareAgentTools(tools, previous, action, id) {
|
|
12790
|
+
const prepared = [];
|
|
12791
|
+
for (const tool of tools) {
|
|
12792
|
+
const old = previous.find((item) => item.name == tool.name);
|
|
12793
|
+
const retained = old?.action == tool.action ? old : void 0;
|
|
12794
|
+
const definition = retained == null ? await action(tool.action) : void 0;
|
|
12795
|
+
const ports = retained?.inputs ?? Object.entries(definition.inputs).map(([handle, port]) => Object.assign({}, port, {
|
|
12796
|
+
handle,
|
|
12797
|
+
source: { kind: "model" }
|
|
12798
|
+
}));
|
|
12799
|
+
const choices = ports.map((port) => port.handle);
|
|
12800
|
+
for (const input of Object.keys(tool.inputs ?? {})) if (!choices.includes(input)) throw new AuthoringToolInputError({
|
|
12801
|
+
tool: tool.name,
|
|
12802
|
+
action: tool.action,
|
|
12803
|
+
input,
|
|
12804
|
+
choices
|
|
12805
|
+
});
|
|
12806
|
+
const { inputs: sources, ...settings } = tool;
|
|
12807
|
+
prepared.push({
|
|
12808
|
+
...settings,
|
|
12809
|
+
id: old?.id ?? id(),
|
|
12810
|
+
action: definition?.actionId ?? tool.action,
|
|
12811
|
+
inputs: ports.map((port) => sources != null && Object.hasOwn(sources, port.handle) ? Object.assign({}, port, { source: sources[port.handle] }) : port)
|
|
12812
|
+
});
|
|
12813
|
+
}
|
|
12814
|
+
return prepared;
|
|
12815
|
+
}
|
|
12816
|
+
//#endregion
|
|
12817
|
+
//#region src/control/common/authoring.ts
|
|
12818
|
+
var record = (value) => value != null && typeof value == "object" && !Array.isArray(value) ? value : {};
|
|
12819
|
+
var json$2 = (value) => JSON.parse(JSON.stringify(value));
|
|
12820
|
+
var AuthoringError = class extends Error {
|
|
12821
|
+
constructor(code, message, details = {}) {
|
|
12822
|
+
super(message);
|
|
12823
|
+
this.code = code;
|
|
12824
|
+
this.details = details;
|
|
12825
|
+
this.name = "AuthoringError";
|
|
12826
|
+
}
|
|
12827
|
+
};
|
|
12828
|
+
function fail(code, message, details = {}) {
|
|
12829
|
+
throw new AuthoringError(code, message, details);
|
|
12830
|
+
}
|
|
12831
|
+
function nodeAt(content, ref) {
|
|
12832
|
+
return (Object.hasOwn(content.document.graph.nodes, ref) ? content.document.graph.nodes[ref] : void 0) ?? fail("node.not-found", `Node ${JSON.stringify(ref)} does not exist.`, { node: ref });
|
|
12833
|
+
}
|
|
12834
|
+
function taskAt(node) {
|
|
12835
|
+
return node.kind == "task" ? node.task : void 0;
|
|
12836
|
+
}
|
|
12837
|
+
var llmReservedInputs = [
|
|
12838
|
+
"model",
|
|
12839
|
+
"template",
|
|
12840
|
+
"messages"
|
|
12841
|
+
];
|
|
12842
|
+
function inputDefinitions(node) {
|
|
12843
|
+
if (node.kind == "condition") return {};
|
|
12844
|
+
if (node.kind == "poll" || node.kind == "integration") return Object.fromEntries(node.definition.configInputs.flatMap((port) => "handle" in port ? [[port.handle, port]] : []));
|
|
12845
|
+
return nodeInputPorts(node);
|
|
12846
|
+
}
|
|
12847
|
+
function inputMappings(node) {
|
|
12848
|
+
return node.kind == "condition" ? {} : node.kind == "poll" || node.kind == "integration" ? node.config : nodeInputMappings(node);
|
|
12849
|
+
}
|
|
12850
|
+
function typeOf(node) {
|
|
12851
|
+
const task = taskAt(node);
|
|
12852
|
+
return node.kind != "task" ? node.kind : task != null && "executor" in task ? task.executor.kind : "code";
|
|
12853
|
+
}
|
|
12854
|
+
function outwardSource(content, value) {
|
|
12855
|
+
if (Array.isArray(value)) return value.map((v) => outwardSource(content, v));
|
|
12856
|
+
if (value == null || typeof value != "object") return value;
|
|
12857
|
+
const v = record(value);
|
|
12858
|
+
if (v.kind == "node" && typeof v.nodeId == "string" && typeof v.output == "string") return {
|
|
12859
|
+
kind: "output",
|
|
12860
|
+
node: v.nodeId,
|
|
12861
|
+
port: v.output,
|
|
12862
|
+
...v.field == null ? {} : { field: v.field }
|
|
12863
|
+
};
|
|
12864
|
+
if (v.kind == "binding" && typeof v.bindingId == "string") return {
|
|
12865
|
+
kind: "variable",
|
|
12866
|
+
name: content.document.bindings[v.bindingId]?.target ?? "[missing variable]"
|
|
12867
|
+
};
|
|
12868
|
+
if (v.kind == "value") return value;
|
|
12869
|
+
return Object.fromEntries(Object.entries(v).map(([k, item]) => [k, outwardSource(content, item)]));
|
|
12870
|
+
}
|
|
12871
|
+
function authoringEdges(edges) {
|
|
12872
|
+
return edges.map((edge) => edge.sourceHandle == null ? {
|
|
12873
|
+
source: edge.source,
|
|
12874
|
+
target: edge.target
|
|
12875
|
+
} : {
|
|
12876
|
+
source: edge.source,
|
|
12877
|
+
target: edge.target,
|
|
12878
|
+
branch: edge.sourceHandle
|
|
12879
|
+
});
|
|
12880
|
+
}
|
|
12881
|
+
function authoringNode(content, ref) {
|
|
12882
|
+
const node = nodeAt(content, ref), type = typeOf(node), task = taskAt(node);
|
|
12883
|
+
let config = {};
|
|
12884
|
+
const texts = {};
|
|
12885
|
+
if (task != null && "executor" in task) {
|
|
12886
|
+
const { kind: _, ...executor } = task.executor;
|
|
12887
|
+
config = { ...executor };
|
|
12888
|
+
if (task.executor.kind == "agent") {
|
|
12889
|
+
const { prompt, tools, notification, ...rest } = task.executor;
|
|
12890
|
+
const { kind: _agentKind, ...settings } = rest;
|
|
12891
|
+
config = {
|
|
12892
|
+
...settings,
|
|
12893
|
+
inputs: fieldsView([...task.inputs, ...node.kind == "task" ? node.additionalInputs ?? [] : []]),
|
|
12894
|
+
resultSchema: task.outputs.find((port) => "handle" in port)?.jsonSchema ?? { type: "string" },
|
|
12895
|
+
tools: outwardAgentTools(tools)
|
|
12896
|
+
};
|
|
12897
|
+
texts.prompt = prompt;
|
|
12898
|
+
if (notification != null) {
|
|
12899
|
+
const { inputDefinitions: _definitions, ...noticeSettings } = notification;
|
|
12900
|
+
config.notification = noticeSettings;
|
|
12901
|
+
}
|
|
12902
|
+
} else if (task.executor.kind == "llm") config = {
|
|
12903
|
+
...llmConfigurationView(task),
|
|
12904
|
+
inputs: fieldsView([...task.inputs, ...node.kind == "task" ? node.additionalInputs ?? [] : []].filter((port) => !("handle" in port) || !llmReservedInputs.includes(port.handle)))
|
|
12905
|
+
};
|
|
12906
|
+
else if (task.executor.kind == "openapi") config = { ...openApiConfigView(task.executor) };
|
|
12907
|
+
} else if (node.kind == "task" && "moduleId" in node.task) {
|
|
12908
|
+
config = {
|
|
12909
|
+
inputs: fieldsView([...node.task.inputs, ...node.additionalInputs ?? []]),
|
|
12910
|
+
outputs: fieldsView(node.task.outputs),
|
|
12911
|
+
...node.task.capabilities == null ? {} : { capabilities: node.task.capabilities }
|
|
12912
|
+
};
|
|
12913
|
+
texts.code = content.modules[node.task.moduleId]?.source ?? "";
|
|
12914
|
+
} else switch (node.kind) {
|
|
12915
|
+
case "condition":
|
|
12916
|
+
config = { ...conditionConfigurationView(node, (value) => outwardSource(content, value)) };
|
|
12917
|
+
break;
|
|
12918
|
+
case "value":
|
|
12919
|
+
config = {
|
|
12920
|
+
values: Object.fromEntries(node.values.filter((port) => Object.hasOwn(port, "value")).map((port) => [port.handle, port.value])),
|
|
12921
|
+
outputs: fieldsView(node.values.map(({ value: _value, ...port }) => port))
|
|
12922
|
+
};
|
|
12923
|
+
break;
|
|
12924
|
+
case "wait":
|
|
12925
|
+
case "approval":
|
|
12926
|
+
config = { inputs: fieldsView(node.inputDefinitions) };
|
|
12927
|
+
texts.prompt = node.prompt;
|
|
12928
|
+
break;
|
|
12929
|
+
case "webhook":
|
|
12930
|
+
config = {
|
|
12931
|
+
body: fieldsView(node.bodyFields),
|
|
12932
|
+
method: node.method,
|
|
12933
|
+
...node.options == null ? {} : { options: node.options }
|
|
12934
|
+
};
|
|
12935
|
+
break;
|
|
12936
|
+
case "cron":
|
|
12937
|
+
config = { schedule: node.cronTimes };
|
|
12938
|
+
break;
|
|
12939
|
+
case "error":
|
|
12940
|
+
config = node.sourceFlowIds == null ? {} : { sourceFlowIds: node.sourceFlowIds };
|
|
12941
|
+
break;
|
|
12942
|
+
case "poll":
|
|
12943
|
+
case "integration": config = {
|
|
12944
|
+
key: node.definition.key,
|
|
12945
|
+
...node.connectionId == null ? {} : { connectionId: node.connectionId },
|
|
12946
|
+
...node.kind == "poll" ? { schedule: node.pollTimes } : {}
|
|
12947
|
+
};
|
|
12948
|
+
}
|
|
12949
|
+
const edges = authoringEdges(content.document.graph.edges);
|
|
12950
|
+
return {
|
|
12951
|
+
ref,
|
|
12952
|
+
type,
|
|
12953
|
+
name: node.name ?? ref,
|
|
12954
|
+
readOnly: false,
|
|
12955
|
+
...node.description == null ? {} : { description: node.description },
|
|
12956
|
+
...node.icon == null ? {} : { icon: node.icon },
|
|
12957
|
+
..."timeoutMs" in node && node.timeoutMs != null ? { timeoutMs: node.timeoutMs } : {},
|
|
12958
|
+
..."maxExecutions" in node && node.maxExecutions != null ? { maxExecutions: node.maxExecutions } : {},
|
|
12959
|
+
config: json$2(config),
|
|
12960
|
+
texts: Object.fromEntries(Object.entries(texts).map(([field, text]) => [field, {
|
|
12961
|
+
lines: text.split("\n").length,
|
|
12962
|
+
characters: text.length
|
|
12963
|
+
}])),
|
|
12964
|
+
inputs: outwardSource(content, inputMappings(node)),
|
|
12965
|
+
inputPorts: fieldsView(Object.entries(inputDefinitions(node)).map(([handle, port]) => Object.assign({}, port, { handle }))),
|
|
12966
|
+
outputPorts: fieldsView(Object.entries(nodeOutputPorts(node)).map(([handle, port]) => Object.assign({}, port, { handle }))),
|
|
12967
|
+
...task != null && "executor" in task && task.executor.kind == "openapi" ? { authenticationChoices: openApiAuthenticationChoices(task.executor) } : {},
|
|
12968
|
+
incoming: edges.filter((e) => e.target == ref),
|
|
12969
|
+
outgoing: edges.filter((e) => e.source == ref)
|
|
12970
|
+
};
|
|
12971
|
+
}
|
|
12972
|
+
function textAt(content, node, field) {
|
|
12973
|
+
if (field == "code" && node.kind == "task" && "moduleId" in node.task) return content.modules[node.task.moduleId]?.source ?? fail("text.missing", "Node source is missing.");
|
|
12974
|
+
const task = taskAt(node);
|
|
12975
|
+
if (field == "prompt" && task != null && "executor" in task && task.executor.kind == "agent") return task.executor.prompt;
|
|
12976
|
+
if (field == "prompt" && (node.kind == "wait" || node.kind == "approval")) return node.prompt;
|
|
12977
|
+
return fail("text.unsupported", `This node has no ${field} field.`);
|
|
12978
|
+
}
|
|
12979
|
+
function readAuthoring(content, query = {}) {
|
|
12980
|
+
const q = authoringReadSchema.parse(query);
|
|
12981
|
+
if (q.text != null) {
|
|
12982
|
+
const lines = textAt(content, nodeAt(content, q.text.node), q.text.field).split("\n");
|
|
12983
|
+
const selected = lines.slice(q.text.start - 1, q.text.start - 1 + q.text.lines);
|
|
12984
|
+
let count = 0, characters = 0;
|
|
12985
|
+
for (const line of selected) {
|
|
12986
|
+
if (characters + line.length + 1 > 24e3) break;
|
|
12987
|
+
characters += line.length + 1;
|
|
12988
|
+
count++;
|
|
12989
|
+
}
|
|
12990
|
+
if (count == 0 && selected.length > 0) fail("text.line-too-large", "Selected line exceeds 24000 characters; use search to locate a smaller edit.", {
|
|
12991
|
+
node: q.text.node,
|
|
12992
|
+
field: q.text.field
|
|
12993
|
+
});
|
|
12994
|
+
const end = q.text.start - 1 + count;
|
|
12995
|
+
return { text: {
|
|
12996
|
+
...q.text,
|
|
12997
|
+
content: selected.slice(0, count).join("\n"),
|
|
12998
|
+
totalLines: lines.length,
|
|
12999
|
+
...end < lines.length ? { nextStart: end + 1 } : {},
|
|
13000
|
+
truncated: end < lines.length
|
|
13001
|
+
} };
|
|
13002
|
+
}
|
|
13003
|
+
if (q.nodes != null) return { nodes: q.nodes.map((ref) => authoringNode(content, ref)) };
|
|
13004
|
+
return {
|
|
13005
|
+
nodes: Object.keys(content.document.graph.nodes).map((ref) => {
|
|
13006
|
+
const node = authoringNode(content, ref);
|
|
13007
|
+
return {
|
|
13008
|
+
ref,
|
|
13009
|
+
type: node.type,
|
|
13010
|
+
name: node.name,
|
|
13011
|
+
readOnly: node.readOnly,
|
|
13012
|
+
inputHandles: Object.keys(node.inputPorts),
|
|
13013
|
+
outputHandles: Object.keys(node.outputPorts),
|
|
13014
|
+
inputs: compactValue(node.inputs),
|
|
13015
|
+
texts: node.texts
|
|
13016
|
+
};
|
|
13017
|
+
}),
|
|
13018
|
+
edges: authoringEdges(content.document.graph.edges)
|
|
13019
|
+
};
|
|
13020
|
+
}
|
|
13021
|
+
function compactValue(value, depth = 0) {
|
|
13022
|
+
if (depth >= 4 && value != null && typeof value == "object") return { truncated: true };
|
|
13023
|
+
if (typeof value == "string") return value.length > 160 ? {
|
|
13024
|
+
preview: value.slice(0, 160),
|
|
13025
|
+
truncated: true
|
|
13026
|
+
} : value;
|
|
13027
|
+
if (Array.isArray(value)) return value.length > 8 ? {
|
|
13028
|
+
preview: value.slice(0, 8).map((v) => compactValue(v, depth + 1)),
|
|
13029
|
+
truncated: true
|
|
13030
|
+
} : value.map((v) => compactValue(v, depth + 1));
|
|
13031
|
+
if (value != null && typeof value == "object") return Object.fromEntries([...Object.entries(value).slice(0, 8).map(([key, v]) => [key, compactValue(v, depth + 1)]), ...Object.keys(value).length > 8 ? [["truncated", true]] : []]);
|
|
13032
|
+
return value;
|
|
13033
|
+
}
|
|
13034
|
+
function searchAuthoring(content, query) {
|
|
13035
|
+
const q = authoringSearchSchema.parse(query), needle = q.query.toLowerCase();
|
|
13036
|
+
const matches = [];
|
|
13037
|
+
for (const [ref, node] of Object.entries(content.document.graph.nodes)) {
|
|
13038
|
+
const view = authoringNode(content, ref);
|
|
13039
|
+
if (q.type != null && q.type != view.type) continue;
|
|
13040
|
+
const fields = {
|
|
13041
|
+
name: view.name,
|
|
13042
|
+
description: view.description ?? "",
|
|
13043
|
+
inputs: JSON.stringify(view.inputs),
|
|
13044
|
+
config: JSON.stringify(view.config),
|
|
13045
|
+
...Object.fromEntries(Object.keys(view.texts).map((field) => [field, textAt(content, node, field)]))
|
|
13046
|
+
};
|
|
13047
|
+
for (const [field, value] of Object.entries(fields)) for (const [index, line] of value.split("\n").entries()) {
|
|
13048
|
+
const at = line.toLowerCase().indexOf(needle);
|
|
13049
|
+
if (at >= 0) matches.push({
|
|
13050
|
+
node: ref,
|
|
13051
|
+
field,
|
|
13052
|
+
line: index + 1,
|
|
13053
|
+
excerpt: line.slice(Math.max(0, at - 100), at + Math.max(needle.length, 100))
|
|
13054
|
+
});
|
|
13055
|
+
}
|
|
13056
|
+
}
|
|
13057
|
+
const end = q.offset + q.limit;
|
|
13058
|
+
return {
|
|
13059
|
+
matches: matches.slice(q.offset, end),
|
|
13060
|
+
total: matches.length,
|
|
13061
|
+
...end < matches.length ? { nextOffset: end } : {}
|
|
13062
|
+
};
|
|
13063
|
+
}
|
|
13064
|
+
function merge(base, patch) {
|
|
13065
|
+
if (patch == null || typeof patch != "object" || Array.isArray(patch)) return patch;
|
|
13066
|
+
const result = { ...record(base) };
|
|
13067
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
13068
|
+
if ([
|
|
13069
|
+
"__proto__",
|
|
13070
|
+
"constructor",
|
|
13071
|
+
"prototype"
|
|
13072
|
+
].includes(key)) fail("edit.invalid-field", `Invalid field ${key}.`);
|
|
13073
|
+
Object.defineProperty(result, key, {
|
|
13074
|
+
value: merge(result[key], value),
|
|
13075
|
+
enumerable: true,
|
|
13076
|
+
writable: true,
|
|
13077
|
+
configurable: true
|
|
13078
|
+
});
|
|
13079
|
+
}
|
|
13080
|
+
return result;
|
|
13081
|
+
}
|
|
13082
|
+
function clearPath(value, path) {
|
|
13083
|
+
let current = value;
|
|
13084
|
+
for (const part of path.slice(0, -1)) {
|
|
13085
|
+
if (!Object.hasOwn(current, part) || Array.isArray(current[part]) || current[part] == null || typeof current[part] != "object") fail("edit.invalid-field", `Cannot clear ${path.join(".")}.`);
|
|
13086
|
+
current = record(current[part]);
|
|
13087
|
+
}
|
|
13088
|
+
const last = path.at(-1);
|
|
13089
|
+
if (!Object.hasOwn(current, last)) fail("edit.invalid-field", `Cannot clear absent field ${path.join(".")}.`);
|
|
13090
|
+
delete current[last];
|
|
13091
|
+
}
|
|
13092
|
+
async function compileAuthoring(base, request, host) {
|
|
13093
|
+
const parsed = authoringRequestSchema.parse(request);
|
|
13094
|
+
let content = base, index = 0, sequence = 0;
|
|
13095
|
+
const operations = [], aliases = {};
|
|
13096
|
+
const touchedModules = /* @__PURE__ */ new Set();
|
|
13097
|
+
function fresh(label) {
|
|
13098
|
+
return host.id(`${index}:${label}:${sequence++}`);
|
|
13099
|
+
}
|
|
13100
|
+
function apply(changes) {
|
|
13101
|
+
const checked = decodeChangeOperations(changes);
|
|
13102
|
+
content = applyFlowChanges(content, checked);
|
|
13103
|
+
operations.push(...checked);
|
|
13104
|
+
}
|
|
13105
|
+
function resolve(ref) {
|
|
13106
|
+
return ref.startsWith("$") ? (Object.hasOwn(aliases, ref.slice(1)) ? aliases[ref.slice(1)] : void 0) ?? fail("node.alias-missing", `Unknown alias ${ref}.`) : ref;
|
|
13107
|
+
}
|
|
13108
|
+
function source(value) {
|
|
13109
|
+
if (value.kind == "output") {
|
|
13110
|
+
const ref = resolve(value.node);
|
|
13111
|
+
const choices = Object.keys(nodeOutputPorts(nodeAt(content, ref)));
|
|
13112
|
+
const port = value.port ?? (choices.length == 1 ? choices[0] : void 0);
|
|
13113
|
+
if (port == null) fail("source.port-required", "Choose an output name; this node does not have exactly one output.", {
|
|
13114
|
+
node: ref,
|
|
13115
|
+
choices
|
|
13116
|
+
});
|
|
13117
|
+
return {
|
|
13118
|
+
kind: "node",
|
|
13119
|
+
nodeId: ref,
|
|
13120
|
+
output: port,
|
|
13121
|
+
...value.field == null ? {} : { field: value.field }
|
|
13122
|
+
};
|
|
13123
|
+
}
|
|
13124
|
+
const existing = Object.entries(content.document.bindings).find(([, binding]) => binding.target == value.name);
|
|
13125
|
+
const bindingId = existing?.[0] ?? fresh("binding");
|
|
13126
|
+
if (existing == null) apply([{
|
|
13127
|
+
kind: "binding.create",
|
|
13128
|
+
bindingId,
|
|
13129
|
+
binding: {
|
|
13130
|
+
kind: "variable",
|
|
13131
|
+
target: value.name
|
|
13132
|
+
}
|
|
13133
|
+
}]);
|
|
13134
|
+
return {
|
|
13135
|
+
kind: "binding",
|
|
13136
|
+
bindingId
|
|
13137
|
+
};
|
|
13138
|
+
}
|
|
13139
|
+
function replace(ref, node) {
|
|
13140
|
+
const before = nodeAt(content, ref);
|
|
13141
|
+
if (!dequal(before, node)) apply([{
|
|
13142
|
+
kind: "graph.node.replace",
|
|
13143
|
+
nodeId: ref,
|
|
13144
|
+
before,
|
|
13145
|
+
node
|
|
13146
|
+
}]);
|
|
13147
|
+
}
|
|
13148
|
+
function taskNode(ref, task) {
|
|
13149
|
+
const node = nodeAt(content, ref);
|
|
13150
|
+
if (node.kind != "task" || !("executor" in node.task)) fail("node.invalid-type", "Expected a managed node.");
|
|
13151
|
+
replace(ref, {
|
|
13152
|
+
...node,
|
|
13153
|
+
task
|
|
13154
|
+
});
|
|
13155
|
+
}
|
|
13156
|
+
async function connectorTask(config, name) {
|
|
13157
|
+
const action = await host.action(String(config.action));
|
|
13158
|
+
return {
|
|
13159
|
+
name,
|
|
13160
|
+
executor: {
|
|
13161
|
+
kind: "connector",
|
|
13162
|
+
action: action.actionId,
|
|
13163
|
+
...config.connectionId == null ? {} : { connectionId: String(config.connectionId) }
|
|
13164
|
+
},
|
|
13165
|
+
inputs: Object.entries(action.inputs).map(([handle, port]) => Object.assign({ handle }, port)),
|
|
13166
|
+
outputs: Object.entries(action.outputs).map(([handle, port]) => Object.assign({ handle }, port))
|
|
13167
|
+
};
|
|
13168
|
+
}
|
|
13169
|
+
async function configure(ref, patch = {}, clear = []) {
|
|
13170
|
+
const node = nodeAt(content, ref), view = authoringNode(content, ref), type = view.type;
|
|
13171
|
+
const update = record(merge({
|
|
13172
|
+
name: view.name,
|
|
13173
|
+
...view.description == null ? {} : { description: view.description },
|
|
13174
|
+
...view.icon == null ? {} : { icon: view.icon },
|
|
13175
|
+
...view.timeoutMs == null ? {} : { timeoutMs: view.timeoutMs },
|
|
13176
|
+
...view.maxExecutions == null ? {} : { maxExecutions: view.maxExecutions },
|
|
13177
|
+
config: view.config
|
|
13178
|
+
}, patch));
|
|
13179
|
+
const explicit = (key) => Object.hasOwn(record(patch.config), key) || clear.some((path) => path[0] == "config" && path[1] == key);
|
|
13180
|
+
if (type == "openapi" && Object.hasOwn(record(patch.config), "authentication")) record(update.config).authentication = record(patch.config).authentication;
|
|
13181
|
+
for (const path of clear) clearPath(update, path);
|
|
13182
|
+
if (typeof update.name != "string") fail("node.name-required", "Node name cannot be cleared.");
|
|
13183
|
+
const config = authoringConfigurations[type].parse(update.config);
|
|
13184
|
+
const { config: _, ...metadata } = update;
|
|
13185
|
+
const { name: _name, description: _description, icon: _icon, ...rest } = node;
|
|
13186
|
+
let next = {
|
|
13187
|
+
...rest,
|
|
13188
|
+
...metadata
|
|
13189
|
+
};
|
|
13190
|
+
if ("inputs" in node) {
|
|
13191
|
+
const clean = { ...next };
|
|
13192
|
+
if (!Object.hasOwn(update, "timeoutMs")) delete clean.timeoutMs;
|
|
13193
|
+
if (!Object.hasOwn(update, "maxExecutions")) delete clean.maxExecutions;
|
|
13194
|
+
next = clean;
|
|
13195
|
+
} else if (update.timeoutMs != null || update.maxExecutions != null) fail("node.invalid-field", "Trigger nodes do not have execution limits.");
|
|
13196
|
+
function taskInputs(task, reserved = []) {
|
|
13197
|
+
if (node.kind != "task") throw new Error("Expected a task.");
|
|
13198
|
+
const fields = record(config.inputs);
|
|
13199
|
+
for (const key of reserved) if (Object.hasOwn(fields, key)) fail("input.reserved", `Configure ${key} through config.${key} or input.set.`, {
|
|
13200
|
+
node: ref,
|
|
13201
|
+
input: key
|
|
13202
|
+
});
|
|
13203
|
+
const extraNames = new Set(node.additionalInputs?.map((port) => port.handle) ?? []);
|
|
13204
|
+
const main = Object.fromEntries(Object.entries(fields).filter(([key]) => !extraNames.has(key)));
|
|
13205
|
+
for (const port of task.inputs) if ("handle" in port && (reserved.includes(port.handle) || extraNames.has(port.handle) && Object.hasOwn(fields, port.handle))) main[port.handle] = fieldsView([port])[port.handle];
|
|
13206
|
+
if (node.additionalInputs != null) {
|
|
13207
|
+
const extra = Object.fromEntries(Object.entries(fields).filter(([key]) => extraNames.has(key)));
|
|
13208
|
+
for (const port of node.additionalInputs) if (reserved.includes(port.handle)) extra[port.handle] = fieldsView([port])[port.handle];
|
|
13209
|
+
next = {
|
|
13210
|
+
...next,
|
|
13211
|
+
additionalInputs: fieldsToPorts(extra, node.additionalInputs)
|
|
13212
|
+
};
|
|
13213
|
+
}
|
|
13214
|
+
return fieldsToPorts(main, task.inputs);
|
|
13215
|
+
}
|
|
13216
|
+
if (node.kind == "task" && "moduleId" in node.task) {
|
|
13217
|
+
const inputs = taskInputs(node.task);
|
|
13218
|
+
next = {
|
|
13219
|
+
...next,
|
|
13220
|
+
task: {
|
|
13221
|
+
moduleId: node.task.moduleId,
|
|
13222
|
+
name: String(update.name),
|
|
13223
|
+
...config,
|
|
13224
|
+
inputs,
|
|
13225
|
+
outputs: fieldsToPorts(config.outputs, node.task.outputs)
|
|
13226
|
+
}
|
|
13227
|
+
};
|
|
13228
|
+
} else if (node.kind == "task" && "executor" in node.task) {
|
|
13229
|
+
const before = node.task;
|
|
13230
|
+
let task;
|
|
13231
|
+
if (type == "connector") task = config.action == (before.executor.kind == "connector" ? before.executor.action : "") ? {
|
|
13232
|
+
...before,
|
|
13233
|
+
name: String(update.name),
|
|
13234
|
+
executor: {
|
|
13235
|
+
kind: "connector",
|
|
13236
|
+
...config
|
|
13237
|
+
}
|
|
13238
|
+
} : await connectorTask(config, String(update.name));
|
|
13239
|
+
else if (type == "decision") task = decisionTask(config.questions, String(update.name));
|
|
13240
|
+
else if (type == "openapi") task = await prepareOpenApiTask(config, before, (url) => host.openapi(url), String(update.name), {
|
|
13241
|
+
authentication: explicit("authentication"),
|
|
13242
|
+
serverUrl: explicit("serverUrl")
|
|
13243
|
+
});
|
|
13244
|
+
else if (type == "llm") {
|
|
13245
|
+
task = prepareLlmConfiguration(config, before, String(update.name));
|
|
13246
|
+
task = {
|
|
13247
|
+
...task,
|
|
13248
|
+
inputs: taskInputs(task, llmReservedInputs)
|
|
13249
|
+
};
|
|
13250
|
+
} else {
|
|
13251
|
+
const { inputs: _inputs, resultSchema, notification, tools, ...executor } = config;
|
|
13252
|
+
const prepared = {
|
|
13253
|
+
...executor,
|
|
13254
|
+
kind: type,
|
|
13255
|
+
...before.executor.kind == "agent" ? { prompt: before.executor.prompt } : {}
|
|
13256
|
+
};
|
|
13257
|
+
if (type == "agent") {
|
|
13258
|
+
const previous = before.executor.kind == "agent" ? before.executor : void 0;
|
|
13259
|
+
Object.assign(prepared, { tools: await prepareAgentTools(tools, previous?.tools ?? [], (id) => host.action(id), () => fresh("tool")) });
|
|
13260
|
+
Reflect.deleteProperty(prepared, "notification");
|
|
13261
|
+
if (notification != null) {
|
|
13262
|
+
if (dequal(record(view.config).notification, notification) && previous?.notification != null) Object.assign(prepared, { notification: previous.notification });
|
|
13263
|
+
else {
|
|
13264
|
+
const settings = record(notification);
|
|
13265
|
+
const definition = await connectorTask(settings, `${update.name} notification`);
|
|
13266
|
+
Object.assign(prepared, { notification: {
|
|
13267
|
+
action: settings.action,
|
|
13268
|
+
...settings.connectionId == null ? {} : { connectionId: settings.connectionId },
|
|
13269
|
+
inputDefinitions: definition.inputs,
|
|
13270
|
+
messageHandle: settings.messageHandle,
|
|
13271
|
+
inputs: settings.inputs
|
|
13272
|
+
} });
|
|
13273
|
+
}
|
|
13274
|
+
}
|
|
13275
|
+
}
|
|
13276
|
+
const outputs = dequal(record(view.config).resultSchema, resultSchema) ? before.outputs : before.outputs.map((port) => "handle" in port ? {
|
|
13277
|
+
...port,
|
|
13278
|
+
jsonSchema: resultSchema
|
|
13279
|
+
} : port);
|
|
13280
|
+
task = {
|
|
13281
|
+
name: String(update.name),
|
|
13282
|
+
inputs: type == "agent" ? taskInputs(before) : before.inputs,
|
|
13283
|
+
outputs,
|
|
13284
|
+
executor: prepared
|
|
13285
|
+
};
|
|
13286
|
+
}
|
|
13287
|
+
next = {
|
|
13288
|
+
...next,
|
|
13289
|
+
task
|
|
13290
|
+
};
|
|
13291
|
+
} else switch (node.kind) {
|
|
13292
|
+
case "condition":
|
|
13293
|
+
next = {
|
|
13294
|
+
...next,
|
|
13295
|
+
...prepareConditionConfiguration(config, source)
|
|
13296
|
+
};
|
|
13297
|
+
break;
|
|
13298
|
+
case "value": {
|
|
13299
|
+
const fields = { ...record(config.outputs) };
|
|
13300
|
+
for (const key of Object.keys(record(config.values))) if (!Object.hasOwn(fields, key)) fields[key] = {};
|
|
13301
|
+
const values = fieldsToPorts(fields, node.values.map(({ value: _value, ...port }) => port)).filter((port) => "handle" in port).map((port) => Object.assign({}, port, Object.hasOwn(record(config.values), port.handle) ? { value: record(config.values)[port.handle] } : {}));
|
|
13302
|
+
next = {
|
|
13303
|
+
...next,
|
|
13304
|
+
values
|
|
13305
|
+
};
|
|
13306
|
+
break;
|
|
13307
|
+
}
|
|
13308
|
+
case "wait":
|
|
13309
|
+
case "approval":
|
|
13310
|
+
next = {
|
|
13311
|
+
...next,
|
|
13312
|
+
inputDefinitions: fieldsToPorts(config.inputs, node.inputDefinitions)
|
|
13313
|
+
};
|
|
13314
|
+
break;
|
|
13315
|
+
case "webhook": {
|
|
13316
|
+
const { body, ...settings } = config;
|
|
13317
|
+
const { options: _options, ...withoutOptions } = next;
|
|
13318
|
+
next = {
|
|
13319
|
+
...withoutOptions,
|
|
13320
|
+
...settings,
|
|
13321
|
+
bodyFields: fieldsToPorts(body, node.bodyFields)
|
|
13322
|
+
};
|
|
13323
|
+
break;
|
|
13324
|
+
}
|
|
13325
|
+
case "cron":
|
|
13326
|
+
next = {
|
|
13327
|
+
...next,
|
|
13328
|
+
cronTimes: config.schedule
|
|
13329
|
+
};
|
|
13330
|
+
break;
|
|
13331
|
+
case "poll":
|
|
13332
|
+
case "integration": {
|
|
13333
|
+
if (config.key != node.definition.key) fail("trigger.key-immutable", "Create a new node to change its Trigger type.");
|
|
13334
|
+
const { connectionId: _connection, ...withoutConnection } = next;
|
|
13335
|
+
next = {
|
|
13336
|
+
...withoutConnection,
|
|
13337
|
+
...config.connectionId == null ? {} : { connectionId: config.connectionId },
|
|
13338
|
+
...node.kind == "poll" ? { pollTimes: config.schedule } : {}
|
|
13339
|
+
};
|
|
13340
|
+
break;
|
|
13341
|
+
}
|
|
13342
|
+
default: {
|
|
13343
|
+
const fields = { ...next };
|
|
13344
|
+
for (const key of Object.keys(record(view.config))) delete fields[key];
|
|
13345
|
+
next = {
|
|
13346
|
+
...fields,
|
|
13347
|
+
...config
|
|
13348
|
+
};
|
|
13349
|
+
}
|
|
13350
|
+
}
|
|
13351
|
+
replace(ref, next);
|
|
13352
|
+
}
|
|
13353
|
+
async function setText(ref, field, text) {
|
|
13354
|
+
const node = nodeAt(content, ref), before = textAt(content, node, field);
|
|
13355
|
+
if (before == text) return;
|
|
13356
|
+
if (field == "code" && node.kind == "task" && "moduleId" in node.task) {
|
|
13357
|
+
const moduleId = node.task.moduleId, module = content.modules[moduleId];
|
|
13358
|
+
const shared = Object.values(content.document.graph.nodes).some((n) => n.kind == "task" && "moduleId" in n.task && n.task.moduleId == moduleId && n !== node) || Object.values(content.modules).some((m) => m.imports.includes(moduleId));
|
|
13359
|
+
const imports$1 = await imports(text);
|
|
13360
|
+
if (shared) {
|
|
13361
|
+
const id = fresh("module");
|
|
13362
|
+
apply([{
|
|
13363
|
+
kind: "module.create",
|
|
13364
|
+
moduleId: id,
|
|
13365
|
+
module: {
|
|
13366
|
+
...module,
|
|
13367
|
+
source: text,
|
|
13368
|
+
imports: imports$1
|
|
13369
|
+
}
|
|
13370
|
+
}]);
|
|
13371
|
+
replace(ref, {
|
|
13372
|
+
...node,
|
|
13373
|
+
task: {
|
|
13374
|
+
...node.task,
|
|
13375
|
+
moduleId: id
|
|
13376
|
+
}
|
|
13377
|
+
});
|
|
13378
|
+
} else apply([{
|
|
13379
|
+
kind: "module.source.replace",
|
|
13380
|
+
moduleId,
|
|
13381
|
+
beforeSource: before,
|
|
13382
|
+
beforeImports: module.imports,
|
|
13383
|
+
source: text,
|
|
13384
|
+
imports: imports$1
|
|
13385
|
+
}]);
|
|
13386
|
+
} else if (node.kind == "task" && "executor" in node.task) {
|
|
13387
|
+
const task = node.task;
|
|
13388
|
+
taskNode(ref, {
|
|
13389
|
+
...task,
|
|
13390
|
+
executor: {
|
|
13391
|
+
...task.executor,
|
|
13392
|
+
prompt: text
|
|
13393
|
+
}
|
|
13394
|
+
});
|
|
13395
|
+
} else if (node.kind == "wait" || node.kind == "approval") replace(ref, {
|
|
13396
|
+
...node,
|
|
13397
|
+
prompt: text
|
|
13398
|
+
});
|
|
13399
|
+
}
|
|
13400
|
+
async function setInput(ref, input, value) {
|
|
13401
|
+
const node = nodeAt(content, ref);
|
|
13402
|
+
if (node.kind == "condition") fail("input.unsupported", "Edit the branch condition operands through config.branches.", {
|
|
13403
|
+
node: ref,
|
|
13404
|
+
field: "config.branches"
|
|
13405
|
+
});
|
|
13406
|
+
if (node.kind == "poll" || node.kind == "integration") {
|
|
13407
|
+
if (!Object.hasOwn(inputDefinitions(node), input)) fail("input.not-found", `Unknown input ${input}.`, {
|
|
13408
|
+
node: ref,
|
|
13409
|
+
input,
|
|
13410
|
+
choices: Object.keys(inputDefinitions(node))
|
|
13411
|
+
});
|
|
13412
|
+
if (value.kind != "value" && value.kind != "unset" && value.kind != "default") fail("input.source-unsupported", "Trigger parameters accept only value, unset or default; they cannot depend on execution outputs or variables.", {
|
|
13413
|
+
node: ref,
|
|
13414
|
+
input,
|
|
13415
|
+
allowed: [
|
|
13416
|
+
"value",
|
|
13417
|
+
"unset",
|
|
13418
|
+
"default"
|
|
13419
|
+
]
|
|
13420
|
+
});
|
|
13421
|
+
const config = { ...node.config };
|
|
13422
|
+
if (value.kind == "default") delete config[input];
|
|
13423
|
+
else config[input] = value;
|
|
13424
|
+
replace(ref, {
|
|
13425
|
+
...node,
|
|
13426
|
+
config
|
|
13427
|
+
});
|
|
13428
|
+
return;
|
|
13429
|
+
}
|
|
13430
|
+
if (!Object.hasOwn(inputDefinitions(node), input)) {
|
|
13431
|
+
const type = typeOf(node);
|
|
13432
|
+
if (![
|
|
13433
|
+
"agent",
|
|
13434
|
+
"code",
|
|
13435
|
+
"llm",
|
|
13436
|
+
"wait",
|
|
13437
|
+
"approval"
|
|
13438
|
+
].includes(type)) fail("input.not-found", `Unknown input ${input}.`, {
|
|
13439
|
+
node: ref,
|
|
13440
|
+
input,
|
|
13441
|
+
choices: Object.keys(inputDefinitions(node))
|
|
13442
|
+
});
|
|
13443
|
+
if (type == "llm" && llmReservedInputs.includes(input)) fail("input.not-found", `Missing built-in LLM input ${input}.`, {
|
|
13444
|
+
node: ref,
|
|
13445
|
+
input,
|
|
13446
|
+
choices: Object.keys(inputDefinitions(node))
|
|
13447
|
+
});
|
|
13448
|
+
await configure(ref, { config: { inputs: { [input]: {} } } });
|
|
13449
|
+
}
|
|
13450
|
+
const mapping = value.kind == "default" ? void 0 : value.kind == "value" || value.kind == "unset" ? value : {
|
|
13451
|
+
kind: "sources",
|
|
13452
|
+
sources: (value.kind == "sources" ? value.sources : [value]).map(source)
|
|
13453
|
+
};
|
|
13454
|
+
const before = nodeInputMappings(nodeAt(content, ref))[input];
|
|
13455
|
+
if (!dequal(before, mapping)) apply([{
|
|
13456
|
+
kind: "graph.node.input.set",
|
|
13457
|
+
nodeId: ref,
|
|
13458
|
+
handle: input,
|
|
13459
|
+
before,
|
|
13460
|
+
...mapping == null ? {} : { value: mapping }
|
|
13461
|
+
}]);
|
|
13462
|
+
}
|
|
13463
|
+
for (const edit of parsed.edits) {
|
|
13464
|
+
try {
|
|
13465
|
+
switch (edit.op) {
|
|
13466
|
+
case "node.add": {
|
|
13467
|
+
if (Object.hasOwn(aliases, edit.as)) fail("node.alias-duplicate", `Duplicate alias ${edit.as}.`);
|
|
13468
|
+
const nodeId = host.id(`node:${edit.as}`), identity = {
|
|
13469
|
+
nodeId,
|
|
13470
|
+
moduleId: fresh("module")
|
|
13471
|
+
}, name = edit.name;
|
|
13472
|
+
aliases[edit.as] = nodeId;
|
|
13473
|
+
const config = edit.config ?? {};
|
|
13474
|
+
let changes;
|
|
13475
|
+
switch (edit.type) {
|
|
13476
|
+
case "code":
|
|
13477
|
+
changes = createCodeTask(identity, name, void 0, {
|
|
13478
|
+
inputs: [],
|
|
13479
|
+
outputs: config.outputs == null ? defaultCodeTaskPorts.outputs : []
|
|
13480
|
+
});
|
|
13481
|
+
break;
|
|
13482
|
+
case "agent":
|
|
13483
|
+
changes = createAgentTask(identity, name, {
|
|
13484
|
+
inputs: [],
|
|
13485
|
+
prompt: edit.prompt ?? ""
|
|
13486
|
+
});
|
|
13487
|
+
break;
|
|
13488
|
+
case "llm":
|
|
13489
|
+
changes = createLlmTask(identity, name, "chat", "Generated response.").map((change) => change.kind == "graph.node.create" && change.node.kind == "task" && "executor" in change.node.task ? Object.assign({}, change, { node: Object.assign({}, change.node, { task: initialAuthoringLlmTask(change.node.task) }) }) : change);
|
|
13490
|
+
break;
|
|
13491
|
+
case "decision":
|
|
13492
|
+
changes = createDecisionTask(identity, name);
|
|
13493
|
+
break;
|
|
13494
|
+
case "connector":
|
|
13495
|
+
changes = createManagedTask(identity, await connectorTask(config, name));
|
|
13496
|
+
break;
|
|
13497
|
+
case "openapi":
|
|
13498
|
+
changes = createManagedTask(identity, await prepareOpenApiTask(authoringConfigurations.openapi.parse(config), void 0, (url) => host.openapi(url), name));
|
|
13499
|
+
break;
|
|
13500
|
+
case "condition":
|
|
13501
|
+
changes = createCondition(nodeId, name);
|
|
13502
|
+
break;
|
|
13503
|
+
case "value":
|
|
13504
|
+
changes = createValue(nodeId, name, []);
|
|
13505
|
+
break;
|
|
13506
|
+
case "wait":
|
|
13507
|
+
changes = createWait(nodeId, name);
|
|
13508
|
+
break;
|
|
13509
|
+
case "approval":
|
|
13510
|
+
changes = createApproval(nodeId, name);
|
|
13511
|
+
break;
|
|
13512
|
+
case "poll":
|
|
13513
|
+
case "integration": {
|
|
13514
|
+
const definition = host.trigger(String(config.key));
|
|
13515
|
+
if (definition.type != edit.type) fail("trigger.type-mismatch", "Trigger key has a different type.");
|
|
13516
|
+
changes = createProviderTrigger(nodeId, definition, {
|
|
13517
|
+
name,
|
|
13518
|
+
config: {}
|
|
13519
|
+
});
|
|
13520
|
+
break;
|
|
13521
|
+
}
|
|
13522
|
+
default: changes = [{
|
|
13523
|
+
kind: "graph.node.create",
|
|
13524
|
+
nodeId,
|
|
13525
|
+
node: {
|
|
13526
|
+
kind: edit.type,
|
|
13527
|
+
name,
|
|
13528
|
+
...edit.type == "cron" ? { cronTimes: [{
|
|
13529
|
+
type: "every",
|
|
13530
|
+
unit: "hour",
|
|
13531
|
+
value: 1
|
|
13532
|
+
}] } : {},
|
|
13533
|
+
...edit.type == "webhook" ? {
|
|
13534
|
+
method: "POST",
|
|
13535
|
+
bodyFields: []
|
|
13536
|
+
} : {}
|
|
13537
|
+
}
|
|
13538
|
+
}];
|
|
13539
|
+
}
|
|
13540
|
+
apply(changes);
|
|
13541
|
+
await configure(nodeId, { config });
|
|
13542
|
+
const added = nodeAt(content, nodeId);
|
|
13543
|
+
if (added.kind == "task") replace(nodeId, {
|
|
13544
|
+
...added,
|
|
13545
|
+
inputs: {}
|
|
13546
|
+
});
|
|
13547
|
+
if (edit.code != null) await setText(nodeId, "code", edit.code);
|
|
13548
|
+
if (edit.prompt != null) await setText(nodeId, "prompt", edit.prompt);
|
|
13549
|
+
for (const [input, binding] of Object.entries(edit.inputs ?? {})) await setInput(nodeId, input, binding);
|
|
13550
|
+
break;
|
|
13551
|
+
}
|
|
13552
|
+
case "node.update":
|
|
13553
|
+
await configure(resolve(edit.node), edit.set, edit.clear);
|
|
13554
|
+
break;
|
|
13555
|
+
case "node.remove": {
|
|
13556
|
+
const ref = resolve(edit.node), node = nodeAt(content, ref);
|
|
13557
|
+
if (node.kind == "task" && "moduleId" in node.task) touchedModules.add(node.task.moduleId);
|
|
13558
|
+
apply([{
|
|
13559
|
+
kind: "graph.node.delete",
|
|
13560
|
+
nodeId: ref
|
|
13561
|
+
}]);
|
|
13562
|
+
break;
|
|
13563
|
+
}
|
|
13564
|
+
case "input.set":
|
|
13565
|
+
await setInput(resolve(edit.node), edit.input, edit.source);
|
|
13566
|
+
break;
|
|
13567
|
+
case "edge.connect":
|
|
13568
|
+
case "edge.disconnect": {
|
|
13569
|
+
const from = resolve(edit.source), to = resolve(edit.target);
|
|
13570
|
+
nodeAt(content, from);
|
|
13571
|
+
nodeAt(content, to);
|
|
13572
|
+
const edge = {
|
|
13573
|
+
source: from,
|
|
13574
|
+
target: to,
|
|
13575
|
+
...edit.branch == null ? {} : { sourceHandle: edit.branch }
|
|
13576
|
+
};
|
|
13577
|
+
const exists = content.document.graph.edges.some((e) => dequal(e, edge));
|
|
13578
|
+
if (edit.op == "edge.connect" != exists) apply([{
|
|
13579
|
+
kind: edit.op == "edge.connect" ? "graph.edge.connect" : "graph.edge.disconnect",
|
|
13580
|
+
edge
|
|
13581
|
+
}]);
|
|
13582
|
+
break;
|
|
13583
|
+
}
|
|
13584
|
+
case "text.set":
|
|
13585
|
+
await setText(resolve(edit.node), edit.field, edit.text);
|
|
13586
|
+
break;
|
|
13587
|
+
case "text.edit": {
|
|
13588
|
+
const ref = resolve(edit.node), value = textAt(content, nodeAt(content, ref), edit.field), count = value.split(edit.oldText).length - 1;
|
|
13589
|
+
if (count != 1) fail("text.match-count", `Expected one exact match, found ${count}. Read the field and include more context.`, {
|
|
13590
|
+
node: ref,
|
|
13591
|
+
field: edit.field,
|
|
13592
|
+
matches: count
|
|
13593
|
+
});
|
|
13594
|
+
await setText(ref, edit.field, value.replace(edit.oldText, () => edit.newText));
|
|
13595
|
+
break;
|
|
13596
|
+
}
|
|
13597
|
+
}
|
|
13598
|
+
} catch (error) {
|
|
13599
|
+
if (error instanceof AuthoringError || error instanceof AuthoringToolInputError || error instanceof AuthoringOpenApiAuthenticationError) throw new AuthoringError(error.code, error.message, {
|
|
13600
|
+
...error.details,
|
|
13601
|
+
editIndex: index
|
|
13602
|
+
});
|
|
13603
|
+
throw new AuthoringError("edit.invalid", error instanceof Error ? error.message : String(error), { editIndex: index });
|
|
13604
|
+
}
|
|
13605
|
+
index++;
|
|
13606
|
+
}
|
|
13607
|
+
for (const moduleId of touchedModules) if (!Object.values(content.document.graph.nodes).some((n) => n.kind == "task" && "moduleId" in n.task && n.task.moduleId == moduleId) && !Object.values(content.modules).some((m) => m.imports.includes(moduleId))) apply([{
|
|
13608
|
+
kind: "module.delete",
|
|
13609
|
+
moduleId
|
|
13610
|
+
}]);
|
|
13611
|
+
const cleaned = cleanVariableBindings(base, operations);
|
|
13612
|
+
return {
|
|
13613
|
+
operations: cleaned,
|
|
13614
|
+
content: cleaned.length == 0 ? base : applyFlowChanges(base, cleaned),
|
|
13615
|
+
nodes: aliases
|
|
13616
|
+
};
|
|
13617
|
+
}
|
|
13618
|
+
var escapePointer = (value) => value.replaceAll("~", "~0").replaceAll("/", "~1");
|
|
13619
|
+
function authoringDiagnostics(content, diagnostics) {
|
|
13620
|
+
const nodes = Object.entries(content.document.graph.nodes);
|
|
13621
|
+
return diagnostics.map((diagnostic) => {
|
|
13622
|
+
const affected = nodes.filter(([id, node]) => {
|
|
13623
|
+
const roots = [`/document/graph/nodes/${escapePointer(id)}`];
|
|
13624
|
+
if (node.kind == "task" && "moduleId" in node.task) roots.push(`/modules/${escapePointer(node.task.moduleId)}`);
|
|
13625
|
+
return roots.some((root) => diagnostic.path == root || diagnostic.path.startsWith(`${root}/`));
|
|
13626
|
+
});
|
|
13627
|
+
const message = diagnostic.message.replace(/(CodeModule|Managed Task|Task|Binding) "([^"\n]+)"/g, (_, kind, id) => {
|
|
13628
|
+
if (kind == "Binding") return `Variable "${content.document.bindings[id]?.target ?? "unresolved"}"`;
|
|
13629
|
+
const owners = nodes.filter(([, n]) => n.kind == "task" && kind == "CodeModule" && "moduleId" in n.task && n.task.moduleId == id);
|
|
13630
|
+
return owners.length ? `${kind == "CodeModule" ? "Code for" : "Node"} ${owners.map(([ref, n]) => JSON.stringify(n.name ?? ref)).join(", ")}` : kind == "CodeModule" ? "Referenced code" : "Node configuration";
|
|
13631
|
+
}).replaceAll("CodeModule", "Code");
|
|
13632
|
+
const parts = diagnostic.path.split("/").map((part) => part.replaceAll("~1", "/").replaceAll("~0", "~"));
|
|
13633
|
+
return {
|
|
13634
|
+
code: diagnostic.code,
|
|
13635
|
+
message,
|
|
13636
|
+
nodes: affected.map(([id]) => id),
|
|
13637
|
+
field: affected[0] == null ? "config" : authoringDiagnosticField(content, affected[0][1], parts),
|
|
13638
|
+
...diagnostic.line ? {
|
|
13639
|
+
line: diagnostic.line,
|
|
13640
|
+
column: diagnostic.column
|
|
13641
|
+
} : {}
|
|
13642
|
+
};
|
|
13643
|
+
});
|
|
13644
|
+
}
|
|
13645
|
+
//#endregion
|
|
13646
|
+
//#region src/execution/common/wait.ts
|
|
13647
|
+
/** Shared by decision entry points, the editor, and durable decision storage. */
|
|
13648
|
+
var waitCommentSchema = string().trim().refine((value) => [...value].length <= 2e3, "Wait comment must contain at most 2,000 Unicode code points.").nullable().optional();
|
|
13649
|
+
//#endregion
|
|
13650
|
+
//#region src/control/common/draftOperations.ts
|
|
13651
|
+
var text = string().min(1);
|
|
13652
|
+
var json$1 = json$5();
|
|
13653
|
+
var triggerCreate = strictObject({
|
|
13654
|
+
kind: literal("graph.trigger.create"),
|
|
13655
|
+
nodeId: text,
|
|
13656
|
+
key: text,
|
|
13657
|
+
connectionId: text.optional(),
|
|
13658
|
+
name: text.optional(),
|
|
13659
|
+
config: record$3(text, json$1),
|
|
13660
|
+
schedule: triggerScheduleSchema.readonly().optional()
|
|
13661
|
+
});
|
|
13662
|
+
function decodeDraftOperations(value) {
|
|
13663
|
+
checkJsonDepth(value);
|
|
13664
|
+
return array(unknown()).min(1).parse(value).map((candidate, index) => {
|
|
13665
|
+
const { kind } = parseOperation(candidate, index, object$1({ kind: text }).parse);
|
|
13666
|
+
return kind == "graph.trigger.create" ? parseOperation(candidate, index, triggerCreate.parse) : decodeChangeOperation(candidate, index);
|
|
13667
|
+
});
|
|
13668
|
+
}
|
|
13669
|
+
function draftOperationsSchema(kind) {
|
|
13670
|
+
if (kind != null && kind != "graph.trigger.create") return changeOperationsSchema(kind);
|
|
13671
|
+
const trigger = toJSONSchema(triggerCreate);
|
|
13672
|
+
if (kind == "graph.trigger.create") return trigger;
|
|
13673
|
+
const schema = changeOperationsSchema();
|
|
13674
|
+
return {
|
|
13675
|
+
...schema,
|
|
13676
|
+
items: { anyOf: [schema.items, trigger] }
|
|
13677
|
+
};
|
|
13678
|
+
}
|
|
13679
|
+
function resolveDraftOperations(operations, definition) {
|
|
13680
|
+
return operations.flatMap((operation) => {
|
|
13681
|
+
if (operation.kind != "graph.trigger.create") return [operation];
|
|
13682
|
+
const snapshot = definition(operation.key);
|
|
13683
|
+
if (snapshot.type != "poll" && operation.schedule != null) throw new Error("Only Poll triggers accept a schedule.");
|
|
13684
|
+
return createProviderTrigger(operation.nodeId, snapshot, operation);
|
|
13685
|
+
});
|
|
13686
|
+
}
|
|
13687
|
+
//#endregion
|
|
13688
|
+
//#region src/control/common/eventSourceSchemas.ts
|
|
13689
|
+
var id$1 = string().min(1).max(256);
|
|
13690
|
+
var eventType = string().regex(/^[a-z][a-z0-9_.]{0,127}$/);
|
|
13691
|
+
var name = string().trim().min(1).max(128);
|
|
13692
|
+
var secret = string().min(1).max(256);
|
|
13693
|
+
var createEventSourceSchema = strictObject({
|
|
13694
|
+
version: literal(1),
|
|
13695
|
+
name,
|
|
13696
|
+
connectionId: id$1,
|
|
13697
|
+
teamId: id$1.nullable(),
|
|
13698
|
+
verificationToken: secret,
|
|
13699
|
+
encryptKey: secret,
|
|
13700
|
+
eventTypes: array(eventType).min(1).max(200).refine((values) => new Set(values).size == values.length),
|
|
13701
|
+
manageSubscriptions: boolean()
|
|
13702
|
+
});
|
|
13703
|
+
var updateEventSourceSchema = strictObject({
|
|
13704
|
+
version: literal(1),
|
|
13705
|
+
expectedRevision: int().positive(),
|
|
13706
|
+
name,
|
|
13707
|
+
enabled: boolean(),
|
|
13708
|
+
eventTypes: array(eventType).min(1).max(200).refine((values) => new Set(values).size == values.length),
|
|
13709
|
+
verificationToken: secret.optional(),
|
|
13710
|
+
encryptKey: secret.optional()
|
|
13711
|
+
});
|
|
13712
|
+
var eventSourceRevisionSchema = strictObject({
|
|
13713
|
+
version: literal(1),
|
|
13714
|
+
expectedRevision: int().positive()
|
|
13715
|
+
});
|
|
13716
|
+
//#endregion
|
|
10951
13717
|
//#region src/control/common/authoringExamples.ts
|
|
10952
13718
|
var descriptions = {
|
|
10953
13719
|
"manual": "A Manual start node.",
|
|
@@ -11212,16 +13978,21 @@ function authoringExample(name) {
|
|
|
11212
13978
|
//#endregion
|
|
11213
13979
|
//#region src/control/common/requests.ts
|
|
11214
13980
|
var waitActionBodySchema = strictObject({ comment: waitCommentSchema });
|
|
11215
|
-
var json = json$
|
|
13981
|
+
var json = json$5();
|
|
11216
13982
|
var id = string().min(1);
|
|
11217
13983
|
var version = literal(1);
|
|
11218
13984
|
var flowName = id.refine((value) => value == value.trim() && resourceNameIssue(value) == null, "Flow name is invalid.");
|
|
11219
|
-
var inputs = record$
|
|
13985
|
+
var inputs = record$3(string(), record$3(string(), json));
|
|
11220
13986
|
var trigger = strictObject({
|
|
11221
13987
|
nodeId: id,
|
|
11222
|
-
outputs: record$
|
|
13988
|
+
outputs: record$3(string(), json)
|
|
11223
13989
|
});
|
|
11224
13990
|
var schemas = {
|
|
13991
|
+
authoringCheck: authoringCheckSchema,
|
|
13992
|
+
authoringEdit: authoringRequestSchema,
|
|
13993
|
+
authoringRead: authoringReadSchema,
|
|
13994
|
+
authoringSearch: authoringSearchSchema,
|
|
13995
|
+
authoringSchema: authoringSchemaQuery,
|
|
11225
13996
|
loadOpenApiDocument: strictObject({
|
|
11226
13997
|
url: string().min(1).max(8192),
|
|
11227
13998
|
version
|
|
@@ -11254,7 +14025,7 @@ var schemas = {
|
|
|
11254
14025
|
}),
|
|
11255
14026
|
updatePresentation: strictObject({
|
|
11256
14027
|
expectedRevision: int().positive(),
|
|
11257
|
-
value: record$
|
|
14028
|
+
value: record$3(string(), json),
|
|
11258
14029
|
version
|
|
11259
14030
|
}),
|
|
11260
14031
|
checkFlow: strictObject({
|
|
@@ -11322,6 +14093,11 @@ function decoder(schema) {
|
|
|
11322
14093
|
return (value) => schema.parse(value);
|
|
11323
14094
|
}
|
|
11324
14095
|
var controlRequests = {
|
|
14096
|
+
authoringCheck: decoder(schemas.authoringCheck),
|
|
14097
|
+
authoringEdit: decoder(schemas.authoringEdit),
|
|
14098
|
+
authoringRead: decoder(schemas.authoringRead),
|
|
14099
|
+
authoringSearch: decoder(schemas.authoringSearch),
|
|
14100
|
+
authoringSchema: decoder(schemas.authoringSchema),
|
|
11325
14101
|
loadOpenApiDocument: decoder(schemas.loadOpenApiDocument),
|
|
11326
14102
|
createEventSource: decoder(schemas.createEventSource),
|
|
11327
14103
|
updateEventSource: decoder(schemas.updateEventSource),
|
|
@@ -11353,7 +14129,7 @@ var controlRequests = {
|
|
|
11353
14129
|
versionOnly: decoder(schemas.versionOnly)
|
|
11354
14130
|
};
|
|
11355
14131
|
function controlRequestSchema(name) {
|
|
11356
|
-
const schema = toJSONSchema(schemas[name]);
|
|
14132
|
+
const schema = toJSONSchema(schemas[name], { io: "input" });
|
|
11357
14133
|
if (name == "changeDraft") return {
|
|
11358
14134
|
...schema,
|
|
11359
14135
|
properties: {
|
|
@@ -11364,4 +14140,4 @@ function controlRequestSchema(name) {
|
|
|
11364
14140
|
return schema;
|
|
11365
14141
|
}
|
|
11366
14142
|
//#endregion
|
|
11367
|
-
export { authoringExample, authoringExamples, controlRequestSchema, controlRequests, decodeDraftOperations, draftOperationsSchema, resolveDraftOperations, waitActionBodySchema };
|
|
14143
|
+
export { AuthoringError, authoringCheckResponse, authoringCheckSchema, authoringConfigurations, authoringDiagnosticSchema, authoringDiagnostics, authoringEditResponse, authoringEditSchema, authoringExample, authoringExamples, authoringNode, authoringReadResponse, authoringReadSchema, authoringRequestContract, authoringRequestSchema, authoringSchema, authoringSchemaQuery, authoringSearchResponse, authoringSearchSchema, authoringSourceSchema, authoringTypes, compileAuthoring, controlRequestSchema, controlRequests, decodeDraftOperations, draftOperationsSchema, readAuthoring, resolveDraftOperations, searchAuthoring, waitActionBodySchema };
|