@oomol-lab/open-flow 0.1.0-beta.74 → 0.1.0-beta.75
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/browser/{ContentIcon-CUQHjQIw.js → ContentIcon-FCpKiwjp.js} +2 -1
- package/dist/browser/{FlowCanvas-Dtf8_cQp.js → FlowCanvas-dzRBnlUT.js} +1 -1
- package/dist/browser/{createResourceDialog-DI9pL-Yr.js → createResourceDialog-BeYDdUl-.js} +2 -2
- package/dist/browser/{dialog-BYJGvItc.js → dialog-ZtpsFbl4.js} +284 -13
- package/dist/browser/{exportSvg-BOoy7-Db.js → exportSvg-DqXw1yf-.js} +2 -2
- package/dist/browser/{flowChanges-RL-H4CjD.js → flowChanges-b_5UobFj.js} +285 -44
- package/dist/browser/{flowWorkspace-BkDsETj0.js → flowWorkspace-ItojZbO4.js} +414 -53
- package/dist/browser/preview.css +181 -176
- package/dist/browser/preview.js +955 -182
- package/dist/browser/workbench.css +181 -176
- package/dist/browser/workbench.js +12 -6
- package/dist/browser/{workbenchSelect-BcWPWGzw.js → workbenchSelect-M441Lz0d.js} +1 -1
- package/dist/command/index.js +36 -36
- package/dist/common/authoring.d.ts +4 -4
- package/dist/common/authoringExamples.d.ts +3 -2
- package/dist/common/authoringSchema.d.ts +67 -4
- package/dist/common/control-api-conformance.js +58 -7
- package/dist/common/control-api.js +58 -7
- package/dist/common/control-requests.d.ts +3 -3
- package/dist/common/control-requests.js +234 -62
- package/dist/common/engine-contract.d.ts +1 -0
- package/dist/common/flow-authoring.js +56 -7
- package/dist/common/flow-change.d.ts +1 -1
- package/dist/common/flow-change.js +56 -7
- package/dist/common/flow-encoding.js +55 -7
- package/dist/common/flow-graph.d.ts +2 -1
- package/dist/common/flow-retry.d.ts +1 -1
- package/dist/common/flow-semantics.js +810 -577
- package/dist/common/http-request.d.ts +156 -0
- package/dist/common/http-request.js +5254 -0
- package/dist/common/mcp.d.ts +3 -3
- package/dist/common/mcp.js +58 -7
- package/dist/common/run-events.js +11 -9
- package/dist/common/runtime-contract.js +3 -0
- package/dist/common/scheduler.d.ts +1 -1
- package/dist/common/scheduler.js +70 -21
- package/dist/common/webhook-response.d.ts +0 -2
- package/dist/common/webhook-trigger.js +12 -11
- package/package.json +5 -1
- package/skills/open-flow/references/flow-authoring.md +1 -0
- package/skills/open-flow/references/flow-n8n-conversion.md +19 -15
- package/src/control/common/api.ts +1 -0
- package/src/control/common/authoring.ts +14 -3
- package/src/control/common/authoringExamples.ts +8 -0
- package/src/control/common/authoringSchema.ts +30 -24
- package/src/execution/common/engineContract.ts +4 -0
- package/src/execution/common/events.ts +3 -0
- package/src/execution/common/node-execution.ts +4 -2
- package/src/execution/common/scheduler.ts +1 -0
- package/src/flow/common/change.ts +3 -2
- package/src/flow/common/changeSchema.ts +12 -3
- package/src/flow/common/graph.ts +10 -4
- package/src/flow/common/retry.ts +1 -1
- package/src/flow/common/semantics.ts +60 -3
- package/src/flow/common/webhookResponse.ts +3 -7
- package/src/{openapi → http}/common/authBindings.ts +3 -3
- package/src/http/common/headers.ts +5 -0
- package/src/http/common/httpRequest.ts +251 -0
- package/src/trigger/common/webhook.ts +4 -3
|
@@ -12285,14 +12285,186 @@ function decisionTask(questions = [defaultDecisionQuestion()], name = "AI Decisi
|
|
|
12285
12285
|
};
|
|
12286
12286
|
}
|
|
12287
12287
|
//#endregion
|
|
12288
|
-
//#region src/
|
|
12288
|
+
//#region src/http/common/authBindings.ts
|
|
12289
12289
|
/** Never allow credentials to enter a Revision as literal node inputs. */
|
|
12290
|
-
function
|
|
12290
|
+
function assertHttpAuthBindings(document) {
|
|
12291
12291
|
for (const node of Object.values(document.graph.nodes)) {
|
|
12292
|
-
if (node.kind != "task" || !("executor" in node.task) || node.task.executor.kind
|
|
12293
|
-
for (const [handle, mapping] of Object.entries(node.inputs)) if (handle.startsWith("auth.") && mapping.kind == "value") throw new TypeError("
|
|
12292
|
+
if (node.kind != "task" || !("executor" in node.task) || !["openapi", "http-request"].includes(node.task.executor.kind)) continue;
|
|
12293
|
+
for (const [handle, mapping] of Object.entries(node.inputs)) if (handle.startsWith("auth.") && mapping.kind == "value") throw new TypeError("HTTP authentication accepts deployment variables and upstream outputs only.");
|
|
12294
12294
|
}
|
|
12295
12295
|
}
|
|
12296
|
+
//#endregion
|
|
12297
|
+
//#region src/flow/common/portChanges.ts
|
|
12298
|
+
function renamedPort(previous, next) {
|
|
12299
|
+
const previousNames = new Set(previous.flatMap((port) => "handle" in port ? [port.handle] : []));
|
|
12300
|
+
const nextNames = new Set(next.flatMap((port) => "handle" in port ? [port.handle] : []));
|
|
12301
|
+
const removed = [...previousNames].filter((name) => !nextNames.has(name));
|
|
12302
|
+
const added = [...nextNames].filter((name) => !previousNames.has(name));
|
|
12303
|
+
return removed.length == 1 && added.length == 1 ? [removed[0], added[0]] : void 0;
|
|
12304
|
+
}
|
|
12305
|
+
function renameOutputMapping(mapping, nodeIds, rename) {
|
|
12306
|
+
if (rename == null || mapping.kind != "sources") return mapping;
|
|
12307
|
+
const sources = mapping.sources.map((source) => source.kind == "node" && !source.system && nodeIds.has(source.nodeId) && source.output == rename[0] ? {
|
|
12308
|
+
...source,
|
|
12309
|
+
output: rename[1]
|
|
12310
|
+
} : source);
|
|
12311
|
+
return sources.every((source, index) => source === mapping.sources[index]) ? mapping : {
|
|
12312
|
+
kind: "sources",
|
|
12313
|
+
sources
|
|
12314
|
+
};
|
|
12315
|
+
}
|
|
12316
|
+
/** Carry saved mappings through a field rename and remove only fields absent from the new contract. */
|
|
12317
|
+
function remapInputMappings(mappings, ports, rename) {
|
|
12318
|
+
const inputs = { ...mappings };
|
|
12319
|
+
if (rename != null && Object.hasOwn(inputs, rename[0])) {
|
|
12320
|
+
Object.defineProperty(inputs, rename[1], {
|
|
12321
|
+
value: inputs[rename[0]],
|
|
12322
|
+
enumerable: true,
|
|
12323
|
+
configurable: true,
|
|
12324
|
+
writable: true
|
|
12325
|
+
});
|
|
12326
|
+
delete inputs[rename[0]];
|
|
12327
|
+
}
|
|
12328
|
+
const names = new Set(ports.flatMap((port) => "handle" in port ? [port.handle] : []));
|
|
12329
|
+
for (const name of Object.keys(inputs)) if (!names.has(name)) delete inputs[name];
|
|
12330
|
+
return inputs;
|
|
12331
|
+
}
|
|
12332
|
+
//#endregion
|
|
12333
|
+
//#region src/http/common/httpRequest.ts
|
|
12334
|
+
var parameterSchema = strictObject({
|
|
12335
|
+
mode: _enum(["fields", "object"]).default("fields"),
|
|
12336
|
+
names: array(string()).default([])
|
|
12337
|
+
});
|
|
12338
|
+
var httpRequestConfigSchema = strictObject({
|
|
12339
|
+
method: _enum([
|
|
12340
|
+
"GET",
|
|
12341
|
+
"POST",
|
|
12342
|
+
"PUT",
|
|
12343
|
+
"PATCH",
|
|
12344
|
+
"DELETE",
|
|
12345
|
+
"HEAD",
|
|
12346
|
+
"OPTIONS"
|
|
12347
|
+
]).default("GET"),
|
|
12348
|
+
query: parameterSchema.default({
|
|
12349
|
+
mode: "fields",
|
|
12350
|
+
names: []
|
|
12351
|
+
}),
|
|
12352
|
+
headers: parameterSchema.default({
|
|
12353
|
+
mode: "fields",
|
|
12354
|
+
names: []
|
|
12355
|
+
}),
|
|
12356
|
+
bodyFormat: _enum([
|
|
12357
|
+
"none",
|
|
12358
|
+
"json",
|
|
12359
|
+
"text",
|
|
12360
|
+
"form"
|
|
12361
|
+
]).default("none"),
|
|
12362
|
+
authentication: union([
|
|
12363
|
+
strictObject({ type: literal("none") }),
|
|
12364
|
+
strictObject({ type: _enum(["bearer", "basic"]) }),
|
|
12365
|
+
strictObject({
|
|
12366
|
+
type: literal("apiKey"),
|
|
12367
|
+
name: string(),
|
|
12368
|
+
in: _enum(["header", "query"])
|
|
12369
|
+
})
|
|
12370
|
+
]).default({ type: "none" }),
|
|
12371
|
+
responseFormat: _enum([
|
|
12372
|
+
"auto",
|
|
12373
|
+
"json",
|
|
12374
|
+
"text"
|
|
12375
|
+
]).default("auto"),
|
|
12376
|
+
statusPolicy: _enum(["success", "all"]).default("success")
|
|
12377
|
+
});
|
|
12378
|
+
var httpRequestExecutorSchema = httpRequestConfigSchema.extend({ kind: literal("http-request") });
|
|
12379
|
+
var scalarSchema = { type: [
|
|
12380
|
+
"string",
|
|
12381
|
+
"number",
|
|
12382
|
+
"boolean"
|
|
12383
|
+
] };
|
|
12384
|
+
var queryValueSchema = { anyOf: [scalarSchema, {
|
|
12385
|
+
type: "array",
|
|
12386
|
+
items: scalarSchema
|
|
12387
|
+
}] };
|
|
12388
|
+
var httpHeaderSchema = {
|
|
12389
|
+
type: "object",
|
|
12390
|
+
additionalProperties: { type: "string" }
|
|
12391
|
+
};
|
|
12392
|
+
var httpQuerySchema = {
|
|
12393
|
+
type: "object",
|
|
12394
|
+
additionalProperties: queryValueSchema
|
|
12395
|
+
};
|
|
12396
|
+
function httpAuthHandles(config) {
|
|
12397
|
+
return config.authentication.type == "none" ? [] : config.authentication.type == "basic" ? ["auth.username", "auth.password"] : ["auth.token"];
|
|
12398
|
+
}
|
|
12399
|
+
function retain(ports, old) {
|
|
12400
|
+
const remaining = new Map(ports.map((port) => [port.handle, port]));
|
|
12401
|
+
return [...old.flatMap((item) => {
|
|
12402
|
+
if ("group" in item) return [item];
|
|
12403
|
+
const next = remaining.get(item.handle);
|
|
12404
|
+
if (next == null) return [];
|
|
12405
|
+
remaining.delete(item.handle);
|
|
12406
|
+
return [dequal(item.jsonSchema, next.jsonSchema) && item.nullable == next.nullable ? item : next];
|
|
12407
|
+
}), ...remaining.values()];
|
|
12408
|
+
}
|
|
12409
|
+
function httpRequestTask(config = httpRequestConfigSchema.parse({}), name = "HTTP Request", previous) {
|
|
12410
|
+
const inputs = [{
|
|
12411
|
+
handle: "url",
|
|
12412
|
+
jsonSchema: { type: "string" },
|
|
12413
|
+
nullable: false
|
|
12414
|
+
}];
|
|
12415
|
+
for (const group of ["query", "headers"]) if (config[group].mode == "object") inputs.push({
|
|
12416
|
+
handle: group,
|
|
12417
|
+
jsonSchema: group == "query" ? httpQuerySchema : httpHeaderSchema,
|
|
12418
|
+
nullable: true
|
|
12419
|
+
});
|
|
12420
|
+
else for (const parameterName of config[group].names.filter((value) => value.trim())) inputs.push({
|
|
12421
|
+
handle: `${group == "query" ? "query" : "header"}.${parameterName}`,
|
|
12422
|
+
jsonSchema: group == "query" ? queryValueSchema : { type: "string" },
|
|
12423
|
+
nullable: true
|
|
12424
|
+
});
|
|
12425
|
+
if (config.bodyFormat != "none") inputs.push({
|
|
12426
|
+
handle: "body",
|
|
12427
|
+
jsonSchema: config.bodyFormat == "json" ? {} : config.bodyFormat == "text" ? { type: "string" } : httpQuerySchema,
|
|
12428
|
+
nullable: config.bodyFormat == "json"
|
|
12429
|
+
});
|
|
12430
|
+
inputs.push(...httpAuthHandles(config).map((handle) => ({
|
|
12431
|
+
handle,
|
|
12432
|
+
jsonSchema: { type: "string" },
|
|
12433
|
+
nullable: false
|
|
12434
|
+
})));
|
|
12435
|
+
const outputs = [
|
|
12436
|
+
{
|
|
12437
|
+
handle: "body",
|
|
12438
|
+
jsonSchema: config.responseFormat == "text" ? { type: "string" } : {},
|
|
12439
|
+
nullable: true
|
|
12440
|
+
},
|
|
12441
|
+
{
|
|
12442
|
+
handle: "statusCode",
|
|
12443
|
+
jsonSchema: { type: "integer" },
|
|
12444
|
+
nullable: false
|
|
12445
|
+
},
|
|
12446
|
+
{
|
|
12447
|
+
handle: "headers",
|
|
12448
|
+
jsonSchema: httpHeaderSchema,
|
|
12449
|
+
nullable: false
|
|
12450
|
+
}
|
|
12451
|
+
];
|
|
12452
|
+
return {
|
|
12453
|
+
name,
|
|
12454
|
+
executor: {
|
|
12455
|
+
...config,
|
|
12456
|
+
kind: "http-request"
|
|
12457
|
+
},
|
|
12458
|
+
inputs: retain(inputs, previous?.inputs ?? []),
|
|
12459
|
+
outputs: retain(outputs, previous?.outputs ?? [])
|
|
12460
|
+
};
|
|
12461
|
+
}
|
|
12462
|
+
/** Only a named parameter rename carries a value; changing source modes is not a rename. */
|
|
12463
|
+
function httpRequestInputs(mappings, previous, next) {
|
|
12464
|
+
const candidate = renamedPort(previous.inputs, next.inputs);
|
|
12465
|
+
const rename = candidate != null && ["query.", "header."].some((prefix) => candidate.every((name) => name.startsWith(prefix))) ? candidate : void 0;
|
|
12466
|
+
return remapInputMappings(mappings, next.inputs, rename);
|
|
12467
|
+
}
|
|
12296
12468
|
function checkJsonDepth(value, depth = 0) {
|
|
12297
12469
|
if (depth > 64) throw new TypeError("Value exceeds the maximum JSON depth.");
|
|
12298
12470
|
if (value != null && typeof value == "object") for (const child of Object.values(value)) checkJsonDepth(child, depth + 1);
|
|
@@ -12303,6 +12475,7 @@ var retryNodeTypes = [
|
|
|
12303
12475
|
"code",
|
|
12304
12476
|
"connector",
|
|
12305
12477
|
"openapi",
|
|
12478
|
+
"http-request",
|
|
12306
12479
|
"llm",
|
|
12307
12480
|
"decision"
|
|
12308
12481
|
];
|
|
@@ -12602,7 +12775,8 @@ var managedFields = object$1({
|
|
|
12602
12775
|
kind: literal("workflow"),
|
|
12603
12776
|
flowId: text$1,
|
|
12604
12777
|
revisionId: text$1
|
|
12605
|
-
})
|
|
12778
|
+
}),
|
|
12779
|
+
httpRequestExecutorSchema
|
|
12606
12780
|
])
|
|
12607
12781
|
});
|
|
12608
12782
|
var managed = managedFields.transform(limitDecisionTask);
|
|
@@ -12902,7 +13076,7 @@ function decodeRevisionContent(value) {
|
|
|
12902
13076
|
checkJsonDepth(value);
|
|
12903
13077
|
const content = revision.parse(value);
|
|
12904
13078
|
checkModelVersion(content);
|
|
12905
|
-
|
|
13079
|
+
assertHttpAuthBindings(content.document);
|
|
12906
13080
|
return content;
|
|
12907
13081
|
}
|
|
12908
13082
|
var shapes = {
|
|
@@ -13096,6 +13270,7 @@ function changeOperationsSchema(kind) {
|
|
|
13096
13270
|
return toJSONSchema(schema, { io: "input" });
|
|
13097
13271
|
}
|
|
13098
13272
|
function checkModelVersion(content) {
|
|
13273
|
+
if (content.modelVersion < 11 && Object.values(content.document.graph.nodes).some((candidateNode) => candidateNode.kind == "task" && "executor" in candidateNode.task && candidateNode.task.executor.kind == "http-request")) throw new TypeError("HTTP Request requires Flow model version 11.");
|
|
13099
13274
|
if (content.modelVersion < 11 && Object.values(content.document.graph.nodes).some((candidateNode) => candidateNode.kind == "task" && ("moduleId" in candidateNode.task ? candidateNode.task.capabilities?.some((item) => item.kind == "workflow") : candidateNode.task.executor.kind == "agent" && candidateNode.task.executor.tools.some((item) => item.kind == "workflow")))) throw new TypeError("Workflow tools require Flow model version 11.");
|
|
13100
13275
|
if (content.modelVersion < 10 && Object.values(content.document.graph.nodes).some((candidateNode) => candidateNode.kind == "webhook" && (candidateNode.options?.responseBody != null || candidateNode.options?.responseStatusCodeOutput != null || candidateNode.options?.responseHeadersSource != null || candidateNode.options?.responseHeaderOutputs != null))) throw new TypeError("Dynamic Webhook responses require Flow model version 10.");
|
|
13101
13276
|
if (content.modelVersion < 9 && Object.values(content.document.graph.nodes).some((candidateNode) => "retry" in candidateNode && candidateNode.retry != null)) throw new TypeError("Node retries require Flow model version 9.");
|
|
@@ -13696,6 +13871,7 @@ var authoringTypes = [
|
|
|
13696
13871
|
"llm",
|
|
13697
13872
|
"decision",
|
|
13698
13873
|
"openapi",
|
|
13874
|
+
"http-request",
|
|
13699
13875
|
"condition",
|
|
13700
13876
|
"value",
|
|
13701
13877
|
"wait",
|
|
@@ -13822,6 +13998,7 @@ var authoringConfigurations = {
|
|
|
13822
13998
|
}),
|
|
13823
13999
|
"connector": authoringDefinitionSchemas.connector.omit({ outputMode: true }).strict(),
|
|
13824
14000
|
"openapi": authoringOpenApiSchema,
|
|
14001
|
+
"http-request": httpRequestConfigSchema,
|
|
13825
14002
|
"agent": authoringDefinitionSchemas.agent.omit({
|
|
13826
14003
|
prompt: true,
|
|
13827
14004
|
tools: true
|
|
@@ -14070,21 +14247,21 @@ function authoringSchema(kind) {
|
|
|
14070
14247
|
"wait",
|
|
14071
14248
|
"approval"
|
|
14072
14249
|
].includes(kind),
|
|
14073
|
-
guidance: kind == "webhook-response" ? "Prepare an HTTP response using fixed inputs body (any JSON, default empty text), statusCode (number, default 200) and headers (scalar-valued object, default {}). Select this node in Webhook options.responseBody as {kind: \"webhook-response\", nodeId: \"node reference\", timeoutMs: 30000}. Its first completion responds immediately while the Run continues. It has no business outputs. Multiple response nodes are allowed; each Webhook selects one reachable node." : kind == "outputs" ? "Declare output fields through config.outputDefs. Set their values through node.add.inputs or input.set. Outputs is a singleton execution sink; it waits for its predecessors and produces workflow business outputs independently of node logs. No downstream edges or data references to Outputs are allowed." : kind == "webhook" ? "Use options.responseBody: {kind: \"webhook-response\", nodeId: \"node ID or $alias\", timeoutMs: 30000} to respond on the selected node’s first completion while the Run continues. Body, statusCode and headers come exclusively from that node; clear workflow-output-only status/header references when switching. Alternatively configure options.responseBody as {kind: \"workflow-outputs\", output?: \"top-level output name\", timeoutMs?: 30000} to respond after the Run succeeds. Omit output for the complete object. Connect Webhook to Outputs. Timeout is 1000–60000 ms; HTTP timeout does not cancel the Run. Strings return text; other values return JSON. Only in this mode, options.responseStatusCodeOutput can select a numeric top-level workflow output as the HTTP status, overriding the preserved fixed responseStatusCode (default 200). Its runtime value must be an integer from 200 to 599, excluding 204, 205, 304; missing or invalid values return 500. Use responseHeaders for fixed text headers. In workflow-output mode, responseHeaderOutputs maps header names to top-level output names; values can be string, number or boolean and are converted to text. Alternatively responseHeadersSource: {kind: \"workflow-outputs\", output?: \"object field\"} replaces the entire header object (omit output for all outputs), preserving but ignoring per-header settings. Missing, null, complex or invalid header values return 500 without fallback. Header restrictions and Content-Type policy still apply. Omit responseBody for immediate responseData. Clear options.responseBody, options.responseStatusCodeOutput, options.responseHeadersSource and options.responseHeaderOutputs explicitly to switch back." : kind == "start" ? "Declare workflow inputs through config.inputDefs; read them in Start node details. REST calls and manual runs supply them as trigger.outputs. Downstream nodes bind these parameters as Start outputs. Start has no input sources or defaults; non-nullable parameters are required, and omitted nullable parameters become null." : 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." : kind == "workflow" ? "Select another workflow with config.flowId. A workflow cannot call itself, including in a disconnected node. Owned unpublished or unavailable targets may be saved as incomplete drafts. Use node.refresh to load the current published interface." : kind == "agent" ? "Tools accept Connector Actions or {kind: \"workflow\", flowId, name, description, approval, inputs}. Workflow parameter sources use model, input or value. The platform derives the interface. Refresh a workflow tool with node.refresh and tool: its name." : kind == "code" ? "Select workflows through config.capabilities: [{kind: \"workflow\", flowId, name}]. Call context.workflows.call(name, input) and await its business output. The platform derives input/output types. Refresh a selected workflow tool with node.refresh and tool: its name. Calls obey node and Run time limits." : "Supply business configuration and input data. Fixed definitions are assembled by the tool. Existing constraints and defaults are preserved on partial updates.",
|
|
14250
|
+
guidance: kind == "webhook-response" ? "Prepare an HTTP response using fixed inputs body (any JSON, default empty text), statusCode (number, default 200) and headers (scalar-valued object, default {}). Select this node in Webhook options.responseBody as {kind: \"webhook-response\", nodeId: \"node reference\", timeoutMs: 30000}. Its first completion responds immediately while the Run continues. It has no business outputs. Multiple response nodes are allowed; each Webhook selects one reachable node." : kind == "outputs" ? "Declare output fields through config.outputDefs. Set their values through node.add.inputs or input.set. Outputs is a singleton execution sink; it waits for its predecessors and produces workflow business outputs independently of node logs. No downstream edges or data references to Outputs are allowed." : kind == "webhook" ? "Use options.responseBody: {kind: \"webhook-response\", nodeId: \"node ID or $alias\", timeoutMs: 30000} to respond on the selected node’s first completion while the Run continues. Body, statusCode and headers come exclusively from that node; clear workflow-output-only status/header references when switching. Alternatively configure options.responseBody as {kind: \"workflow-outputs\", output?: \"top-level output name\", timeoutMs?: 30000} to respond after the Run succeeds. Omit output for the complete object. Connect Webhook to Outputs. Timeout is 1000–60000 ms; HTTP timeout does not cancel the Run. Strings return text; other values return JSON. Only in this mode, options.responseStatusCodeOutput can select a numeric top-level workflow output as the HTTP status, overriding the preserved fixed responseStatusCode (default 200). Its runtime value must be an integer from 200 to 599, excluding 204, 205, 304; missing or invalid values return 500. Use responseHeaders for fixed text headers. In workflow-output mode, responseHeaderOutputs maps header names to top-level output names; values can be string, number or boolean and are converted to text. Alternatively responseHeadersSource: {kind: \"workflow-outputs\", output?: \"object field\"} replaces the entire header object (omit output for all outputs), preserving but ignoring per-header settings. Missing, null, complex or invalid header values return 500 without fallback. Header restrictions and Content-Type policy still apply. Omit responseBody for immediate responseData. Clear options.responseBody, options.responseStatusCodeOutput, options.responseHeadersSource and options.responseHeaderOutputs explicitly to switch back." : kind == "start" ? "Declare workflow inputs through config.inputDefs; read them in Start node details. REST calls and manual runs supply them as trigger.outputs. Downstream nodes bind these parameters as Start outputs. Start has no input sources or defaults; non-nullable parameters are required, and omitted nullable parameters become null." : 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 == "http-request" ? "Configure method, query/headers modes and names, bodyFormat, authentication, responseFormat and statusPolicy. Bind url, query.<name>/header.<name> or whole query/headers objects, body and auth.token (Basic: auth.username/auth.password). Credentials accept variables or upstream outputs only. Outputs: body, statusCode, headers. Authentication is replaced as a complete choice." : 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." : kind == "workflow" ? "Select another workflow with config.flowId. A workflow cannot call itself, including in a disconnected node. Owned unpublished or unavailable targets may be saved as incomplete drafts. Use node.refresh to load the current published interface." : kind == "agent" ? "Tools accept Connector Actions or {kind: \"workflow\", flowId, name, description, approval, inputs}. Workflow parameter sources use model, input or value. The platform derives the interface. Refresh a workflow tool with node.refresh and tool: its name." : kind == "code" ? "Select workflows through config.capabilities: [{kind: \"workflow\", flowId, name}]. Call context.workflows.call(name, input) and await its business output. The platform derives input/output types. Refresh a selected workflow tool with node.refresh and tool: its name. Calls obey node and Run time limits." : "Supply business configuration and input data. Fixed definitions are assembled by the tool. Existing constraints and defaults are preserved on partial updates.",
|
|
14074
14251
|
example: {
|
|
14075
14252
|
op: "node.add",
|
|
14076
14253
|
as: "step",
|
|
14077
14254
|
type: kind,
|
|
14078
14255
|
name: "Step",
|
|
14079
14256
|
...{
|
|
14080
|
-
start: { config: { inputDefs: {} } },
|
|
14081
|
-
outputs: { config: { outputDefs: {} } },
|
|
14082
|
-
workflow: { config: { flowId: "<Flow ID>" } },
|
|
14083
|
-
connector: { config: {
|
|
14257
|
+
"start": { config: { inputDefs: {} } },
|
|
14258
|
+
"outputs": { config: { outputDefs: {} } },
|
|
14259
|
+
"workflow": { config: { flowId: "<Flow ID>" } },
|
|
14260
|
+
"connector": { config: {
|
|
14084
14261
|
action: "<Action ID>",
|
|
14085
14262
|
connectionId: "<Connection ID>"
|
|
14086
14263
|
} },
|
|
14087
|
-
poll: { config: {
|
|
14264
|
+
"poll": { config: {
|
|
14088
14265
|
key: "<Trigger key>",
|
|
14089
14266
|
schedule: [{
|
|
14090
14267
|
type: "every",
|
|
@@ -14092,20 +14269,27 @@ function authoringSchema(kind) {
|
|
|
14092
14269
|
value: 5
|
|
14093
14270
|
}]
|
|
14094
14271
|
} },
|
|
14095
|
-
integration: { config: { key: "<Trigger key>" } },
|
|
14096
|
-
|
|
14272
|
+
"integration": { config: { key: "<Trigger key>" } },
|
|
14273
|
+
"http-request": {
|
|
14274
|
+
config: {},
|
|
14275
|
+
inputs: { url: {
|
|
14276
|
+
kind: "value",
|
|
14277
|
+
value: "https://example.com"
|
|
14278
|
+
} }
|
|
14279
|
+
},
|
|
14280
|
+
"openapi": { config: {
|
|
14097
14281
|
sourceUrl: "https://example.com/openapi.json",
|
|
14098
14282
|
path: "/items",
|
|
14099
14283
|
method: "get"
|
|
14100
14284
|
} },
|
|
14101
|
-
code: {
|
|
14285
|
+
"code": {
|
|
14102
14286
|
code: "export default ({value}) => ({result:value})",
|
|
14103
14287
|
inputs: { value: {
|
|
14104
14288
|
kind: "value",
|
|
14105
14289
|
value: "Hello"
|
|
14106
14290
|
} }
|
|
14107
14291
|
},
|
|
14108
|
-
condition: { config: {
|
|
14292
|
+
"condition": { config: {
|
|
14109
14293
|
match: "first",
|
|
14110
14294
|
branches: [{
|
|
14111
14295
|
name: "yes",
|
|
@@ -14122,32 +14306,32 @@ function authoringSchema(kind) {
|
|
|
14122
14306
|
}
|
|
14123
14307
|
}]
|
|
14124
14308
|
} },
|
|
14125
|
-
value: { config: { values: {
|
|
14309
|
+
"value": { config: { values: {
|
|
14126
14310
|
threshold: 100,
|
|
14127
14311
|
region: "EU"
|
|
14128
14312
|
} } },
|
|
14129
|
-
webhook: { config: {
|
|
14313
|
+
"webhook": { config: {
|
|
14130
14314
|
method: "POST",
|
|
14131
14315
|
body: { orderId: {
|
|
14132
14316
|
schema: { type: "string" },
|
|
14133
14317
|
nullable: false
|
|
14134
14318
|
} }
|
|
14135
14319
|
} },
|
|
14136
|
-
wait: {
|
|
14320
|
+
"wait": {
|
|
14137
14321
|
prompt: "Continue processing this order?",
|
|
14138
14322
|
inputs: { order: {
|
|
14139
14323
|
kind: "value",
|
|
14140
14324
|
value: { orderId: "A-1" }
|
|
14141
14325
|
} }
|
|
14142
14326
|
},
|
|
14143
|
-
approval: {
|
|
14327
|
+
"approval": {
|
|
14144
14328
|
prompt: "Approve this order?",
|
|
14145
14329
|
inputs: { order: {
|
|
14146
14330
|
kind: "value",
|
|
14147
14331
|
value: { orderId: "A-1" }
|
|
14148
14332
|
} }
|
|
14149
14333
|
},
|
|
14150
|
-
llm: {
|
|
14334
|
+
"llm": {
|
|
14151
14335
|
config: {
|
|
14152
14336
|
model: { model: "deepseek-v4-flash" },
|
|
14153
14337
|
template: [{
|
|
@@ -14163,7 +14347,7 @@ function authoringSchema(kind) {
|
|
|
14163
14347
|
}
|
|
14164
14348
|
} }
|
|
14165
14349
|
},
|
|
14166
|
-
agent: {
|
|
14350
|
+
"agent": {
|
|
14167
14351
|
config: { model: "deepseek-v4-flash" },
|
|
14168
14352
|
inputs: { orders: {
|
|
14169
14353
|
kind: "value",
|
|
@@ -14999,7 +15183,7 @@ function applyFlowChanges(content, operations) {
|
|
|
14999
15183
|
break;
|
|
15000
15184
|
}
|
|
15001
15185
|
}
|
|
15002
|
-
|
|
15186
|
+
assertHttpAuthBindings(document);
|
|
15003
15187
|
return upgradeDecodedRevisionContent({
|
|
15004
15188
|
document,
|
|
15005
15189
|
modelVersion: 11,
|
|
@@ -15266,42 +15450,6 @@ async function imports(source) {
|
|
|
15266
15450
|
}
|
|
15267
15451
|
}
|
|
15268
15452
|
//#endregion
|
|
15269
|
-
//#region src/flow/common/portChanges.ts
|
|
15270
|
-
function renamedPort(previous, next) {
|
|
15271
|
-
const previousNames = new Set(previous.flatMap((port) => "handle" in port ? [port.handle] : []));
|
|
15272
|
-
const nextNames = new Set(next.flatMap((port) => "handle" in port ? [port.handle] : []));
|
|
15273
|
-
const removed = [...previousNames].filter((name) => !nextNames.has(name));
|
|
15274
|
-
const added = [...nextNames].filter((name) => !previousNames.has(name));
|
|
15275
|
-
return removed.length == 1 && added.length == 1 ? [removed[0], added[0]] : void 0;
|
|
15276
|
-
}
|
|
15277
|
-
function renameOutputMapping(mapping, nodeIds, rename) {
|
|
15278
|
-
if (rename == null || mapping.kind != "sources") return mapping;
|
|
15279
|
-
const sources = mapping.sources.map((source) => source.kind == "node" && !source.system && nodeIds.has(source.nodeId) && source.output == rename[0] ? {
|
|
15280
|
-
...source,
|
|
15281
|
-
output: rename[1]
|
|
15282
|
-
} : source);
|
|
15283
|
-
return sources.every((source, index) => source === mapping.sources[index]) ? mapping : {
|
|
15284
|
-
kind: "sources",
|
|
15285
|
-
sources
|
|
15286
|
-
};
|
|
15287
|
-
}
|
|
15288
|
-
/** Carry saved mappings through a field rename and remove only fields absent from the new contract. */
|
|
15289
|
-
function remapInputMappings(mappings, ports, rename) {
|
|
15290
|
-
const inputs = { ...mappings };
|
|
15291
|
-
if (rename != null && Object.hasOwn(inputs, rename[0])) {
|
|
15292
|
-
Object.defineProperty(inputs, rename[1], {
|
|
15293
|
-
value: inputs[rename[0]],
|
|
15294
|
-
enumerable: true,
|
|
15295
|
-
configurable: true,
|
|
15296
|
-
writable: true
|
|
15297
|
-
});
|
|
15298
|
-
delete inputs[rename[0]];
|
|
15299
|
-
}
|
|
15300
|
-
const names = new Set(ports.flatMap((port) => "handle" in port ? [port.handle] : []));
|
|
15301
|
-
for (const name of Object.keys(inputs)) if (!names.has(name)) delete inputs[name];
|
|
15302
|
-
return inputs;
|
|
15303
|
-
}
|
|
15304
|
-
//#endregion
|
|
15305
15453
|
//#region src/flow/common/nodeChanges.ts
|
|
15306
15454
|
var codeTaskTemplate = `export default async function (inputs, context) {
|
|
15307
15455
|
return { result: inputs.value }
|
|
@@ -16263,7 +16411,10 @@ function authoringNode(content, ref) {
|
|
|
16263
16411
|
inputs: fieldsView([...task.inputs, ...node.kind == "task" ? node.additionalInputs ?? [] : []].filter((port) => !("handle" in port) || !llmReservedInputs.includes(port.handle)))
|
|
16264
16412
|
};
|
|
16265
16413
|
else if (task.executor.kind == "workflow") config = { flowId: task.executor.flowId };
|
|
16266
|
-
else if (task.executor.kind == "
|
|
16414
|
+
else if (task.executor.kind == "http-request") {
|
|
16415
|
+
const { kind: _kind, ...settings } = task.executor;
|
|
16416
|
+
config = settings;
|
|
16417
|
+
} else if (task.executor.kind == "openapi") config = { ...openApiConfigView(task.executor) };
|
|
16267
16418
|
} else if (node.kind == "task" && "moduleId" in node.task) {
|
|
16268
16419
|
config = {
|
|
16269
16420
|
inputs: fieldsView([...node.task.inputs, ...node.additionalInputs ?? []]),
|
|
@@ -16564,7 +16715,7 @@ async function compileAuthoring(base, request, host) {
|
|
|
16564
16715
|
const timing = record(record(patch.config).autoContinue);
|
|
16565
16716
|
if (Object.hasOwn(timing, "kind") && timing.kind != record(record(view.config).autoContinue).kind) record(update.config).autoContinue = timing;
|
|
16566
16717
|
}
|
|
16567
|
-
if (type == "openapi" && Object.hasOwn(record(patch.config), "authentication")) record(update.config).authentication = record(patch.config).authentication;
|
|
16718
|
+
if ((type == "openapi" || type == "http-request") && Object.hasOwn(record(patch.config), "authentication")) record(update.config).authentication = record(patch.config).authentication;
|
|
16568
16719
|
for (const path of clear) clearPath(update, path);
|
|
16569
16720
|
if (typeof update.name != "string") fail("node.name-required", "Node name cannot be cleared.");
|
|
16570
16721
|
const config = authoringConfigurations[type].parse(update.config);
|
|
@@ -16650,7 +16801,13 @@ async function compileAuthoring(base, request, host) {
|
|
|
16650
16801
|
};
|
|
16651
16802
|
} else task = await connectorTask(config, String(update.name));
|
|
16652
16803
|
} else if (type == "decision") task = decisionTask(config.questions, String(update.name));
|
|
16653
|
-
else if (type == "
|
|
16804
|
+
else if (type == "http-request") {
|
|
16805
|
+
task = httpRequestTask(httpRequestConfigSchema.parse(config), String(update.name), before);
|
|
16806
|
+
next = {
|
|
16807
|
+
...next,
|
|
16808
|
+
inputs: httpRequestInputs(node.inputs, before, task)
|
|
16809
|
+
};
|
|
16810
|
+
} else if (type == "openapi") task = await prepareOpenApiTask(config, before, (url) => host.openapi(url), String(update.name), {
|
|
16654
16811
|
authentication: explicit("authentication"),
|
|
16655
16812
|
serverUrl: explicit("serverUrl")
|
|
16656
16813
|
});
|
|
@@ -16991,6 +17148,9 @@ async function compileAuthoring(base, request, host) {
|
|
|
16991
17148
|
case "connector":
|
|
16992
17149
|
changes = createManagedTask(identity, await connectorTask(config, name));
|
|
16993
17150
|
break;
|
|
17151
|
+
case "http-request":
|
|
17152
|
+
changes = createManagedTask(identity, httpRequestTask(httpRequestConfigSchema.parse(config), name));
|
|
17153
|
+
break;
|
|
16994
17154
|
case "openapi":
|
|
16995
17155
|
changes = createManagedTask(identity, await prepareOpenApiTask(authoringConfigurations.openapi.parse(config), void 0, (url) => host.openapi(url), name));
|
|
16996
17156
|
break;
|
|
@@ -17209,6 +17369,7 @@ var descriptions = {
|
|
|
17209
17369
|
"poll": "Gmail polling by key; replace CONNECTION_ID with an active Gmail connection.",
|
|
17210
17370
|
"integration": "Telegram webhook integration by key; replace CONNECTION_ID with an active Telegram connection.",
|
|
17211
17371
|
"decision": "AI Decision evaluates named questions against target and returns a complete answer object per output. Configure target before running.",
|
|
17372
|
+
"http-request": "A single HTTP request. Bind url and request inputs; outputs are body, statusCode and headers.",
|
|
17212
17373
|
"openapi": "A fixed JSON API operation. Replace the example document and URL before running.",
|
|
17213
17374
|
"connector": "A Connector Task and its node. Replace ACTION_ID, CONNECTION_ID and port definitions using connector_get / connector show. Set connectionId to an empty string to defer account configuration; execution will require an account.",
|
|
17214
17375
|
"code": "A JavaScript module and its node. Use Code for custom computation; use Connector Tasks for existing actions.",
|
|
@@ -17252,6 +17413,17 @@ function authoringExample(name) {
|
|
|
17252
17413
|
instructions: "Does the customer need support?"
|
|
17253
17414
|
}]);
|
|
17254
17415
|
break;
|
|
17416
|
+
case "http-request":
|
|
17417
|
+
operations = [...createManagedTask({ nodeId: "http" }, httpRequestTask()), {
|
|
17418
|
+
kind: "graph.node.input.set",
|
|
17419
|
+
nodeId: "http",
|
|
17420
|
+
handle: "url",
|
|
17421
|
+
value: {
|
|
17422
|
+
kind: "value",
|
|
17423
|
+
value: "https://example.com"
|
|
17424
|
+
}
|
|
17425
|
+
}];
|
|
17426
|
+
break;
|
|
17255
17427
|
case "openapi":
|
|
17256
17428
|
operations = createManagedTask({ nodeId: "api" }, openApiTask(selectOperation({
|
|
17257
17429
|
openapi: "3.1.0",
|
|
@@ -6,6 +6,7 @@ export interface EngineContract {
|
|
|
6
6
|
readonly waitAutoContinue?: boolean;
|
|
7
7
|
readonly webhookResponses?: boolean;
|
|
8
8
|
readonly workflowTools?: boolean;
|
|
9
|
+
readonly httpRequests?: boolean;
|
|
9
10
|
}
|
|
10
11
|
export declare const currentEngineContract = "open-flow-engine/v8";
|
|
11
12
|
export declare const nodejsEngineContract = "open-flow-engine/v8/nodejs-compat-v1";
|
|
@@ -3009,12 +3009,12 @@ function decisionTask(questions = [defaultDecisionQuestion()], name = "AI Decisi
|
|
|
3009
3009
|
};
|
|
3010
3010
|
}
|
|
3011
3011
|
//#endregion
|
|
3012
|
-
//#region src/
|
|
3012
|
+
//#region src/http/common/authBindings.ts
|
|
3013
3013
|
/** Never allow credentials to enter a Revision as literal node inputs. */
|
|
3014
|
-
function
|
|
3014
|
+
function assertHttpAuthBindings(document) {
|
|
3015
3015
|
for (const node of Object.values(document.graph.nodes)) {
|
|
3016
|
-
if (node.kind != "task" || !("executor" in node.task) || node.task.executor.kind
|
|
3017
|
-
for (const [handle, mapping] of Object.entries(node.inputs)) if (handle.startsWith("auth.") && mapping.kind == "value") throw new TypeError("
|
|
3016
|
+
if (node.kind != "task" || !("executor" in node.task) || !["openapi", "http-request"].includes(node.task.executor.kind)) continue;
|
|
3017
|
+
for (const [handle, mapping] of Object.entries(node.inputs)) if (handle.startsWith("auth.") && mapping.kind == "value") throw new TypeError("HTTP authentication accepts deployment variables and upstream outputs only.");
|
|
3018
3018
|
}
|
|
3019
3019
|
}
|
|
3020
3020
|
//#endregion
|
|
@@ -8706,6 +8706,52 @@ function preprocess(fn, schema) {
|
|
|
8706
8706
|
function datetime(params) {
|
|
8707
8707
|
return /* @__PURE__ */ _isoDateTime(ZodISODateTime, params);
|
|
8708
8708
|
}
|
|
8709
|
+
//#endregion
|
|
8710
|
+
//#region src/http/common/httpRequest.ts
|
|
8711
|
+
var parameterSchema = strictObject({
|
|
8712
|
+
mode: _enum(["fields", "object"]).default("fields"),
|
|
8713
|
+
names: array(string()).default([])
|
|
8714
|
+
});
|
|
8715
|
+
var httpRequestExecutorSchema = strictObject({
|
|
8716
|
+
method: _enum([
|
|
8717
|
+
"GET",
|
|
8718
|
+
"POST",
|
|
8719
|
+
"PUT",
|
|
8720
|
+
"PATCH",
|
|
8721
|
+
"DELETE",
|
|
8722
|
+
"HEAD",
|
|
8723
|
+
"OPTIONS"
|
|
8724
|
+
]).default("GET"),
|
|
8725
|
+
query: parameterSchema.default({
|
|
8726
|
+
mode: "fields",
|
|
8727
|
+
names: []
|
|
8728
|
+
}),
|
|
8729
|
+
headers: parameterSchema.default({
|
|
8730
|
+
mode: "fields",
|
|
8731
|
+
names: []
|
|
8732
|
+
}),
|
|
8733
|
+
bodyFormat: _enum([
|
|
8734
|
+
"none",
|
|
8735
|
+
"json",
|
|
8736
|
+
"text",
|
|
8737
|
+
"form"
|
|
8738
|
+
]).default("none"),
|
|
8739
|
+
authentication: union([
|
|
8740
|
+
strictObject({ type: literal("none") }),
|
|
8741
|
+
strictObject({ type: _enum(["bearer", "basic"]) }),
|
|
8742
|
+
strictObject({
|
|
8743
|
+
type: literal("apiKey"),
|
|
8744
|
+
name: string(),
|
|
8745
|
+
in: _enum(["header", "query"])
|
|
8746
|
+
})
|
|
8747
|
+
]).default({ type: "none" }),
|
|
8748
|
+
responseFormat: _enum([
|
|
8749
|
+
"auto",
|
|
8750
|
+
"json",
|
|
8751
|
+
"text"
|
|
8752
|
+
]).default("auto"),
|
|
8753
|
+
statusPolicy: _enum(["success", "all"]).default("success")
|
|
8754
|
+
}).extend({ kind: literal("http-request") });
|
|
8709
8755
|
function checkJsonDepth(value, depth = 0) {
|
|
8710
8756
|
if (depth > 64) throw new TypeError("Value exceeds the maximum JSON depth.");
|
|
8711
8757
|
if (value != null && typeof value == "object") for (const child of Object.values(value)) checkJsonDepth(child, depth + 1);
|
|
@@ -8716,6 +8762,7 @@ var retryNodeTypes = [
|
|
|
8716
8762
|
"code",
|
|
8717
8763
|
"connector",
|
|
8718
8764
|
"openapi",
|
|
8765
|
+
"http-request",
|
|
8719
8766
|
"llm",
|
|
8720
8767
|
"decision"
|
|
8721
8768
|
];
|
|
@@ -8992,7 +9039,8 @@ var managedFields = object({
|
|
|
8992
9039
|
kind: literal("workflow"),
|
|
8993
9040
|
flowId: text,
|
|
8994
9041
|
revisionId: text
|
|
8995
|
-
})
|
|
9042
|
+
}),
|
|
9043
|
+
httpRequestExecutorSchema
|
|
8996
9044
|
])
|
|
8997
9045
|
});
|
|
8998
9046
|
var managed = managedFields.transform(limitDecisionTask);
|
|
@@ -9292,7 +9340,7 @@ function decodeRevisionContent(value) {
|
|
|
9292
9340
|
checkJsonDepth(value);
|
|
9293
9341
|
const content = revision.parse(value);
|
|
9294
9342
|
checkModelVersion(content);
|
|
9295
|
-
|
|
9343
|
+
assertHttpAuthBindings(content.document);
|
|
9296
9344
|
return content;
|
|
9297
9345
|
}
|
|
9298
9346
|
var shapes = {
|
|
@@ -9462,6 +9510,7 @@ array(union([...new Map(Object.entries(shapes).map(([kind, shape]) => [kind, sha
|
|
|
9462
9510
|
...shape
|
|
9463
9511
|
})])).values()])).min(1);
|
|
9464
9512
|
function checkModelVersion(content) {
|
|
9513
|
+
if (content.modelVersion < 11 && Object.values(content.document.graph.nodes).some((candidateNode) => candidateNode.kind == "task" && "executor" in candidateNode.task && candidateNode.task.executor.kind == "http-request")) throw new TypeError("HTTP Request requires Flow model version 11.");
|
|
9465
9514
|
if (content.modelVersion < 11 && Object.values(content.document.graph.nodes).some((candidateNode) => candidateNode.kind == "task" && ("moduleId" in candidateNode.task ? candidateNode.task.capabilities?.some((item) => item.kind == "workflow") : candidateNode.task.executor.kind == "agent" && candidateNode.task.executor.tools.some((item) => item.kind == "workflow")))) throw new TypeError("Workflow tools require Flow model version 11.");
|
|
9466
9515
|
if (content.modelVersion < 10 && Object.values(content.document.graph.nodes).some((candidateNode) => candidateNode.kind == "webhook" && (candidateNode.options?.responseBody != null || candidateNode.options?.responseStatusCodeOutput != null || candidateNode.options?.responseHeadersSource != null || candidateNode.options?.responseHeaderOutputs != null))) throw new TypeError("Dynamic Webhook responses require Flow model version 10.");
|
|
9467
9516
|
if (content.modelVersion < 9 && Object.values(content.document.graph.nodes).some((candidateNode) => "retry" in candidateNode && candidateNode.retry != null)) throw new TypeError("Node retries require Flow model version 9.");
|
|
@@ -10167,7 +10216,7 @@ function applyFlowChanges(content, operations) {
|
|
|
10167
10216
|
break;
|
|
10168
10217
|
}
|
|
10169
10218
|
}
|
|
10170
|
-
|
|
10219
|
+
assertHttpAuthBindings(document);
|
|
10171
10220
|
return upgradeDecodedRevisionContent({
|
|
10172
10221
|
document,
|
|
10173
10222
|
modelVersion: 11,
|
|
@@ -113,7 +113,7 @@ export interface ConditionNode extends GraphNodeBase {
|
|
|
113
113
|
readonly matchMode: 'first' | 'all';
|
|
114
114
|
readonly kind: 'condition';
|
|
115
115
|
}
|
|
116
|
-
export type ManagedTaskExecutor = import('./workflow.js').WorkflowExecutor | import('./decision.js').DecisionExecutor | import('./openapi.js').OpenApiExecutor | {
|
|
116
|
+
export type ManagedTaskExecutor = import('./http-request.js').HttpRequestExecutor | import('./workflow.js').WorkflowExecutor | import('./decision.js').DecisionExecutor | import('./openapi.js').OpenApiExecutor | {
|
|
117
117
|
readonly kind: 'connector';
|
|
118
118
|
readonly action: string;
|
|
119
119
|
readonly connectionId?: string;
|