@oomol-lab/open-flow 0.1.0-beta.74 → 0.1.0-beta.76

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.
Files changed (139) hide show
  1. package/README.md +3 -1
  2. package/dist/browser/{ContentIcon-CUQHjQIw.js → ContentIcon-Cm1hbVzW.js} +4 -3
  3. package/dist/browser/{FlowCanvas-Dtf8_cQp.js → FlowCanvas-NzKtla_c.js} +62 -62
  4. package/dist/browser/{createResourceDialog-DI9pL-Yr.js → createResourceDialog-BgdedQqu.js} +3 -3
  5. package/dist/browser/{dialog-BYJGvItc.js → dialog-aSElFFw2.js} +322 -26
  6. package/dist/browser/{exportSvg-BOoy7-Db.js → exportSvg-Dcz4HTo_.js} +2 -2
  7. package/dist/browser/{flowChanges-RL-H4CjD.js → flowChanges-NZyS7HSp.js} +490 -438
  8. package/dist/browser/{flowWorkspace-BkDsETj0.js → flowWorkspace-Bl0SDehy.js} +499 -61
  9. package/dist/browser/preview.css +696 -825
  10. package/dist/browser/preview.js +1399 -717
  11. package/dist/browser/theme.css +114 -262
  12. package/dist/browser/{tooltip-wZJRB9oP.js → tooltip-3XMK9jkr.js} +1 -1
  13. package/dist/browser/{typeScriptSession-CSRwWmZm.js → typeScriptSession-C9sBGOKZ.js} +1 -1
  14. package/dist/browser/ui.css +354 -460
  15. package/dist/browser/ui.js +1 -1
  16. package/dist/browser/workbench.css +696 -825
  17. package/dist/browser/workbench.js +13 -7
  18. package/dist/browser/{workbenchSelect-BcWPWGzw.js → workbenchSelect-DBGP7Y4Z.js} +2 -2
  19. package/dist/command/index.js +41 -43
  20. package/dist/common/authoring.d.ts +5 -5
  21. package/dist/common/authoringExamples.d.ts +3 -2
  22. package/dist/common/authoringSchema.d.ts +70 -4
  23. package/dist/common/connector-proxy.d.ts +1 -1
  24. package/dist/common/control-api-conformance.js +250 -138
  25. package/dist/common/control-api.d.ts +3 -2
  26. package/dist/common/control-api.js +246 -134
  27. package/dist/common/control-requests.d.ts +3 -3
  28. package/dist/common/control-requests.js +353 -79
  29. package/dist/common/cron-trigger.d.ts +2 -1
  30. package/dist/common/decision.d.ts +4 -4
  31. package/dist/common/decision.js +5 -2
  32. package/dist/common/engine-contract.d.ts +6 -1
  33. package/dist/common/event-source-definition.d.ts +1 -1
  34. package/dist/common/event-source-view.d.ts +22 -0
  35. package/dist/common/event-source.d.ts +1 -1
  36. package/dist/common/event-source.js +24 -65
  37. package/dist/common/event-sources.d.ts +0 -21
  38. package/dist/common/flow-authoring.js +90 -19
  39. package/dist/common/flow-change-schema.d.ts +9 -1
  40. package/dist/common/flow-change.d.ts +7 -201
  41. package/dist/common/flow-change.js +96 -23
  42. package/dist/common/flow-encoding.js +89 -21
  43. package/dist/common/flow-graph.d.ts +2 -1
  44. package/dist/common/flow-input-value.d.ts +1 -1
  45. package/dist/common/flow-model.d.ts +121 -0
  46. package/dist/common/flow-notifications.d.ts +1 -1
  47. package/dist/common/flow-retry.d.ts +3 -5
  48. package/dist/common/flow-semantics.js +816 -586
  49. package/dist/common/flow-workflowReferences.d.ts +8 -0
  50. package/dist/common/flowInspection.d.ts +1 -1
  51. package/dist/common/http-hosts.d.ts +6 -0
  52. package/dist/common/http-request.d.ts +164 -0
  53. package/dist/common/http-request.js +5272 -0
  54. package/dist/common/integration-trigger.d.ts +2 -1
  55. package/dist/common/mcp.d.ts +3 -3
  56. package/dist/common/mcp.js +248 -136
  57. package/dist/common/openapi.d.ts +4 -4
  58. package/dist/common/openapi.js +4 -1
  59. package/dist/common/poll-trigger.d.ts +2 -1
  60. package/dist/common/run-events.js +11 -9
  61. package/dist/common/runtime-contract.d.ts +23 -1
  62. package/dist/common/runtime-contract.js +607 -72
  63. package/dist/common/runtime-nodejs-compat.d.ts +44 -0
  64. package/dist/common/runtime-nodejs-compat.js +5870 -0
  65. package/dist/common/scheduler-checkpoint.d.ts +1 -1
  66. package/dist/common/scheduler-node-execution.d.ts +1 -1
  67. package/dist/common/scheduler.d.ts +2 -2
  68. package/dist/common/scheduler.js +95 -25
  69. package/dist/common/trigger-catalog.d.ts +1 -7
  70. package/dist/common/trigger-config-options.d.ts +1 -1
  71. package/dist/common/trigger-config.d.ts +1 -1
  72. package/dist/common/trigger-contract.d.ts +2 -1
  73. package/dist/common/trigger-localization.d.ts +8 -2
  74. package/dist/common/trigger-model.d.ts +101 -0
  75. package/dist/common/webhook-response.d.ts +1 -3
  76. package/dist/common/webhook-trigger.d.ts +3 -1
  77. package/dist/common/webhook-trigger.js +12 -11
  78. package/dist/common/workflow.d.ts +3 -12
  79. package/dist/common/workflow.js +25 -23
  80. package/dist/index.d.ts +41 -14
  81. package/package.json +9 -1
  82. package/skills/open-flow/references/flow-authoring.md +1 -0
  83. package/skills/open-flow/references/flow-n8n-conversion.md +19 -15
  84. package/src/base/common/json.ts +1 -1
  85. package/src/connector/common/proxy.ts +1 -1
  86. package/src/control/common/api.ts +7 -5
  87. package/src/control/common/authoring.ts +14 -3
  88. package/src/control/common/authoringExamples.ts +8 -0
  89. package/src/control/common/authoringSchema.ts +38 -25
  90. package/src/control/common/authoringTools.ts +1 -1
  91. package/src/control/common/conformance.ts +1 -1
  92. package/src/control/common/connectorDecoders.ts +1 -1
  93. package/src/control/common/eventSources.ts +2 -29
  94. package/src/control/common/triggerCatalog.ts +1 -8
  95. package/src/decision/common/decision.ts +15 -7
  96. package/src/event-source/common/definition.ts +1 -1
  97. package/src/event-source/common/index.ts +1 -1
  98. package/src/event-source/common/view.ts +20 -0
  99. package/src/execution/common/checkpoint.ts +1 -1
  100. package/src/execution/common/events.ts +3 -0
  101. package/src/execution/common/node-execution.ts +5 -3
  102. package/src/execution/common/scheduler.ts +2 -1
  103. package/src/flow/common/change.ts +59 -192
  104. package/src/flow/common/changeSchema.ts +39 -5
  105. package/src/flow/common/connectionUsage.ts +1 -1
  106. package/src/flow/common/graph.ts +10 -4
  107. package/src/flow/common/inputValue.ts +1 -1
  108. package/src/flow/common/model.ts +130 -0
  109. package/src/flow/common/modules.ts +1 -1
  110. package/src/flow/common/portChanges.ts +1 -1
  111. package/src/flow/common/retry.ts +3 -5
  112. package/src/flow/common/semantics.ts +71 -7
  113. package/src/flow/common/webhookResponse.ts +4 -8
  114. package/src/flow/common/workflowReferences.ts +31 -0
  115. package/src/http/common/authBindings.ts +9 -0
  116. package/src/http/common/headers.ts +5 -0
  117. package/src/http/common/hosts.ts +13 -0
  118. package/src/http/common/httpRequest.ts +266 -0
  119. package/src/openapi/common/openapi.ts +9 -5
  120. package/src/{execution → runtime}/common/engineContract.ts +24 -15
  121. package/src/runtime/common/nodejsCompat.ts +275 -0
  122. package/src/runtime/common/nodejsGuest.generated.json +47 -0
  123. package/src/runtime/common/runtime.ts +1138 -0
  124. package/src/trigger/common/config.ts +1 -1
  125. package/src/trigger/common/configOptions.ts +1 -1
  126. package/src/trigger/common/contract.ts +2 -1
  127. package/src/trigger/common/cron.ts +2 -1
  128. package/src/trigger/common/integration.ts +2 -1
  129. package/src/trigger/common/model.ts +87 -0
  130. package/src/trigger/common/poll.ts +2 -1
  131. package/src/trigger/common/webhook.ts +7 -4
  132. package/src/trigger/providers/fieldDescriptions.ts +1 -1
  133. package/src/trigger/providers/localization.ts +9 -2
  134. package/src/trigger/providers/remote.ts +1 -1
  135. package/src/types/index.ts +44 -15
  136. package/src/workflow/common/workflow.ts +3 -44
  137. package/src/execution/common/runtime.ts +0 -563
  138. package/src/openapi/common/authBindings.ts +0 -12
  139. /package/src/{control → connector}/common/providerIconSprite.ts +0 -0
@@ -12163,6 +12163,9 @@ function schemaValidationErrors(value, schema) {
12163
12163
  }
12164
12164
  //#endregion
12165
12165
  //#region src/decision/common/decision.ts
12166
+ function isDecisionExecutor(executor) {
12167
+ return executor.kind === "decision";
12168
+ }
12166
12169
  var decisionLimits = {
12167
12170
  choice: 255,
12168
12171
  score: 10
@@ -12185,7 +12188,7 @@ function limitDecisionQuestions(questions) {
12185
12188
  }
12186
12189
  /** Loading an oversized task also updates its previously generated output schemas. */
12187
12190
  function limitDecisionTask(task) {
12188
- if (task.executor.kind !== "decision") return task;
12191
+ if (!isDecisionExecutor(task.executor)) return task;
12189
12192
  const original = task.executor.questions;
12190
12193
  const questions = limitDecisionQuestions(original);
12191
12194
  if (questions === original) return task;
@@ -12285,13 +12288,190 @@ function decisionTask(questions = [defaultDecisionQuestion()], name = "AI Decisi
12285
12288
  };
12286
12289
  }
12287
12290
  //#endregion
12288
- //#region src/openapi/common/authBindings.ts
12289
- /** Never allow credentials to enter a Revision as literal node inputs. */
12290
- function assertOpenApiAuthBindings(document) {
12291
- for (const node of Object.values(document.graph.nodes)) {
12292
- if (node.kind != "task" || !("executor" in node.task) || node.task.executor.kind != "openapi") continue;
12293
- 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.");
12291
+ //#region src/http/common/authBindings.ts
12292
+ /** Never allow credentials to enter a Revision as literal inputs of an OpenAPI or HTTP request node. */
12293
+ function assertHttpAuthBindings(inputs) {
12294
+ for (const [handle, mapping] of Object.entries(inputs)) if (handle.startsWith("auth.") && mapping.kind == "value") throw new TypeError("HTTP authentication accepts deployment variables and upstream outputs only.");
12295
+ }
12296
+ //#endregion
12297
+ //#region src/http/common/hosts.ts
12298
+ /** Hosts of a Code `http` Capability: lowercase DNS names or IPv4 addresses; `*.example.com` matches subdomains only. */
12299
+ var httpHostPattern = /^(?:\*\.)?(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)*[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
12300
+ /** Wildcards must name a registrable suffix, so `*.com` is rejected. */
12301
+ function isHttpHost(value) {
12302
+ return httpHostPattern.test(value) && (!value.startsWith("*.") || value.slice(2).includes("."));
12303
+ }
12304
+ //#endregion
12305
+ //#region src/flow/common/portChanges.ts
12306
+ function renamedPort(previous, next) {
12307
+ const previousNames = new Set(previous.flatMap((port) => "handle" in port ? [port.handle] : []));
12308
+ const nextNames = new Set(next.flatMap((port) => "handle" in port ? [port.handle] : []));
12309
+ const removed = [...previousNames].filter((name) => !nextNames.has(name));
12310
+ const added = [...nextNames].filter((name) => !previousNames.has(name));
12311
+ return removed.length == 1 && added.length == 1 ? [removed[0], added[0]] : void 0;
12312
+ }
12313
+ function renameOutputMapping(mapping, nodeIds, rename) {
12314
+ if (rename == null || mapping.kind != "sources") return mapping;
12315
+ const sources = mapping.sources.map((source) => source.kind == "node" && !source.system && nodeIds.has(source.nodeId) && source.output == rename[0] ? {
12316
+ ...source,
12317
+ output: rename[1]
12318
+ } : source);
12319
+ return sources.every((source, index) => source === mapping.sources[index]) ? mapping : {
12320
+ kind: "sources",
12321
+ sources
12322
+ };
12323
+ }
12324
+ /** Carry saved mappings through a field rename and remove only fields absent from the new contract. */
12325
+ function remapInputMappings(mappings, ports, rename) {
12326
+ const inputs = { ...mappings };
12327
+ if (rename != null && Object.hasOwn(inputs, rename[0])) {
12328
+ Object.defineProperty(inputs, rename[1], {
12329
+ value: inputs[rename[0]],
12330
+ enumerable: true,
12331
+ configurable: true,
12332
+ writable: true
12333
+ });
12334
+ delete inputs[rename[0]];
12294
12335
  }
12336
+ const names = new Set(ports.flatMap((port) => "handle" in port ? [port.handle] : []));
12337
+ for (const name of Object.keys(inputs)) if (!names.has(name)) delete inputs[name];
12338
+ return inputs;
12339
+ }
12340
+ //#endregion
12341
+ //#region src/http/common/httpRequest.ts
12342
+ var parameterSchema = strictObject({
12343
+ mode: _enum(["fields", "object"]).default("fields"),
12344
+ names: array(string()).default([])
12345
+ });
12346
+ var httpRequestConfigSchema = strictObject({
12347
+ method: _enum([
12348
+ "GET",
12349
+ "POST",
12350
+ "PUT",
12351
+ "PATCH",
12352
+ "DELETE",
12353
+ "HEAD",
12354
+ "OPTIONS"
12355
+ ]).default("GET"),
12356
+ query: parameterSchema.default({
12357
+ mode: "fields",
12358
+ names: []
12359
+ }),
12360
+ headers: parameterSchema.default({
12361
+ mode: "fields",
12362
+ names: []
12363
+ }),
12364
+ bodyFormat: _enum([
12365
+ "none",
12366
+ "json",
12367
+ "text",
12368
+ "form"
12369
+ ]).default("none"),
12370
+ authentication: union([
12371
+ strictObject({ type: literal("none") }),
12372
+ strictObject({ type: _enum(["bearer", "basic"]) }),
12373
+ strictObject({
12374
+ type: literal("apiKey"),
12375
+ name: string(),
12376
+ in: _enum(["header", "query"])
12377
+ })
12378
+ ]).default({ type: "none" }),
12379
+ responseFormat: _enum([
12380
+ "auto",
12381
+ "json",
12382
+ "text"
12383
+ ]).default("auto"),
12384
+ statusPolicy: _enum(["success", "all"]).default("success")
12385
+ });
12386
+ var httpRequestExecutorSchema = httpRequestConfigSchema.extend({ kind: literal("http-request") });
12387
+ var scalarSchema = { type: [
12388
+ "string",
12389
+ "number",
12390
+ "boolean"
12391
+ ] };
12392
+ var queryValueSchema = { anyOf: [scalarSchema, {
12393
+ type: "array",
12394
+ items: scalarSchema
12395
+ }] };
12396
+ var httpHeaderSchema = {
12397
+ type: "object",
12398
+ additionalProperties: { type: "string" }
12399
+ };
12400
+ var httpQuerySchema = {
12401
+ type: "object",
12402
+ additionalProperties: queryValueSchema
12403
+ };
12404
+ function httpAuthHandles(config) {
12405
+ return config.authentication.type == "none" ? [] : config.authentication.type == "basic" ? ["auth.username", "auth.password"] : ["auth.token"];
12406
+ }
12407
+ function retain(ports, old) {
12408
+ const remaining = new Map(ports.map((port) => [port.handle, port]));
12409
+ return [...old.flatMap((item) => {
12410
+ if ("group" in item) return [item];
12411
+ const next = remaining.get(item.handle);
12412
+ if (next == null) return [];
12413
+ remaining.delete(item.handle);
12414
+ return [dequal(item.jsonSchema, next.jsonSchema) && item.nullable == next.nullable ? item : next];
12415
+ }), ...remaining.values()];
12416
+ }
12417
+ function httpRequestTask(config = httpRequestConfigSchema.parse({}), name = "HTTP Request", previous) {
12418
+ const inputs = [{
12419
+ handle: "url",
12420
+ jsonSchema: { type: "string" },
12421
+ nullable: false
12422
+ }];
12423
+ for (const group of ["query", "headers"]) if (config[group].mode == "object") inputs.push({
12424
+ handle: group,
12425
+ jsonSchema: group == "query" ? httpQuerySchema : httpHeaderSchema,
12426
+ nullable: true
12427
+ });
12428
+ else for (const parameterName of config[group].names.filter((value) => value.trim())) inputs.push({
12429
+ handle: `${group == "query" ? "query" : "header"}.${parameterName}`,
12430
+ jsonSchema: group == "query" ? queryValueSchema : { type: "string" },
12431
+ nullable: true
12432
+ });
12433
+ if (config.bodyFormat != "none") inputs.push({
12434
+ handle: "body",
12435
+ jsonSchema: config.bodyFormat == "json" ? {} : config.bodyFormat == "text" ? { type: "string" } : httpQuerySchema,
12436
+ nullable: config.bodyFormat == "json"
12437
+ });
12438
+ inputs.push(...httpAuthHandles(config).map((handle) => ({
12439
+ handle,
12440
+ jsonSchema: { type: "string" },
12441
+ nullable: false
12442
+ })));
12443
+ const outputs = [
12444
+ {
12445
+ handle: "body",
12446
+ jsonSchema: config.responseFormat == "text" ? { type: "string" } : {},
12447
+ nullable: true
12448
+ },
12449
+ {
12450
+ handle: "statusCode",
12451
+ jsonSchema: { type: "integer" },
12452
+ nullable: false
12453
+ },
12454
+ {
12455
+ handle: "headers",
12456
+ jsonSchema: httpHeaderSchema,
12457
+ nullable: false
12458
+ }
12459
+ ];
12460
+ return {
12461
+ name,
12462
+ executor: {
12463
+ ...config,
12464
+ kind: "http-request"
12465
+ },
12466
+ inputs: retain(inputs, previous?.inputs ?? []),
12467
+ outputs: retain(outputs, previous?.outputs ?? [])
12468
+ };
12469
+ }
12470
+ /** Only a named parameter rename carries a value; changing source modes is not a rename. */
12471
+ function httpRequestInputs(mappings, previous, next) {
12472
+ const candidate = renamedPort(previous.inputs, next.inputs);
12473
+ const rename = candidate != null && ["query.", "header."].some((prefix) => candidate.every((name) => name.startsWith(prefix))) ? candidate : void 0;
12474
+ return remapInputMappings(mappings, next.inputs, rename);
12295
12475
  }
12296
12476
  function checkJsonDepth(value, depth = 0) {
12297
12477
  if (depth > 64) throw new TypeError("Value exceeds the maximum JSON depth.");
@@ -12303,6 +12483,7 @@ var retryNodeTypes = [
12303
12483
  "code",
12304
12484
  "connector",
12305
12485
  "openapi",
12486
+ "http-request",
12306
12487
  "llm",
12307
12488
  "decision"
12308
12489
  ];
@@ -12492,7 +12673,15 @@ var workflowCapabilitySchema = strictObject({
12492
12673
  inputs: array(port),
12493
12674
  outputs: array(port).nullable()
12494
12675
  });
12495
- var capability = union([connectorCapabilitySchema, workflowCapabilitySchema]);
12676
+ var httpCapabilitySchema = strictObject({
12677
+ kind: literal("http"),
12678
+ hosts: array(text$1.refine(isHttpHost, "Use a lowercase host name or IPv4 address, optionally prefixed by \"*.\" for subdomains.")).min(1).max(20).describe("Hosts Code may call with context.fetch. \"*.example.com\" matches subdomains only.")
12679
+ });
12680
+ var capability = union([
12681
+ connectorCapabilitySchema,
12682
+ workflowCapabilitySchema,
12683
+ httpCapabilitySchema
12684
+ ]);
12496
12685
  var inline = object$1({
12497
12686
  ...ports,
12498
12687
  name: text$1,
@@ -12602,7 +12791,8 @@ var managedFields = object$1({
12602
12791
  kind: literal("workflow"),
12603
12792
  flowId: text$1,
12604
12793
  revisionId: text$1
12605
- })
12794
+ }),
12795
+ httpRequestExecutorSchema
12606
12796
  ])
12607
12797
  });
12608
12798
  var managed = managedFields.transform(limitDecisionTask);
@@ -12871,7 +13061,8 @@ var revision = object$1({
12871
13061
  literal(8),
12872
13062
  literal(9),
12873
13063
  literal(10),
12874
- literal(11)
13064
+ literal(11),
13065
+ literal(12)
12875
13066
  ]),
12876
13067
  document,
12877
13068
  modules: record$3(text$1, module)
@@ -12902,7 +13093,7 @@ function decodeRevisionContent(value) {
12902
13093
  checkJsonDepth(value);
12903
13094
  const content = revision.parse(value);
12904
13095
  checkModelVersion(content);
12905
- assertOpenApiAuthBindings(content.document);
13096
+ assertDocumentHttpAuthBindings(content.document);
12906
13097
  return content;
12907
13098
  }
12908
13099
  var shapes = {
@@ -13096,6 +13287,8 @@ function changeOperationsSchema(kind) {
13096
13287
  return toJSONSchema(schema, { io: "input" });
13097
13288
  }
13098
13289
  function checkModelVersion(content) {
13290
+ if (content.modelVersion < 12 && Object.values(content.document.graph.nodes).some((candidateNode) => candidateNode.kind == "task" && "moduleId" in candidateNode.task && candidateNode.task.capabilities?.some((item) => item.kind == "http"))) throw new TypeError("Code HTTP access requires Flow model version 12.");
13291
+ 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
13292
  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
13293
  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
13294
  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.");
@@ -13110,6 +13303,81 @@ function checkModelVersion(content) {
13110
13303
  if (content.modelVersion < 6 && Object.values(content.document.graph.nodes).some((candidateNode) => candidateNode.kind == "task" && "executor" in candidateNode.task)) throw new TypeError("Node-owned managed Tasks require Flow model version 6.");
13111
13304
  if (content.modelVersion < 5 && Object.values(content.document.graph.nodes).some((itemNode) => itemNode.kind == "error")) throw new TypeError("Error workflows require Flow model version 5.");
13112
13305
  }
13306
+ function assertDocumentHttpAuthBindings(content) {
13307
+ for (const graphNode of Object.values(content.graph.nodes)) if (graphNode.kind == "task" && "executor" in graphNode.task && ["openapi", "http-request"].includes(graphNode.task.executor.kind)) assertHttpAuthBindings(graphNode.inputs);
13308
+ }
13309
+ //#endregion
13310
+ //#region src/runtime/common/engineContract.ts
13311
+ /** v9 is a single contract: the Node compatibility builtins, `context.fetch`, and no `context.egress`. */
13312
+ var currentEngineContract = "open-flow-engine/v9";
13313
+ /** The published v8 Node compatibility contract, retained for existing Publications and Runs. */
13314
+ var nodejsEngineContract = "open-flow-engine/v8/nodejs-compat-v1";
13315
+ var platformSource = (contract) => `export const engineContract = ${JSON.stringify(contract)}
13316
+ export function identity(value) { return value }
13317
+ `;
13318
+ var v8Contract = {
13319
+ workflowTools: true,
13320
+ httpRequests: true,
13321
+ waitAutoContinue: true,
13322
+ webhookResponses: true,
13323
+ platformExports: /* @__PURE__ */ new Set(["engineContract", "identity"]),
13324
+ platformModule: "open-flow:platform",
13325
+ platformSource: platformSource("open-flow-engine/v8")
13326
+ };
13327
+ var nodejsContract = {
13328
+ ...v8Contract,
13329
+ builtinModules: new Set([
13330
+ "assert",
13331
+ "assert/strict",
13332
+ "buffer",
13333
+ "console",
13334
+ "constants",
13335
+ "crypto",
13336
+ "events",
13337
+ "fs",
13338
+ "fs/promises",
13339
+ "os",
13340
+ "path",
13341
+ "path/posix",
13342
+ "process",
13343
+ "punycode",
13344
+ "querystring",
13345
+ "stream",
13346
+ "stream/promises",
13347
+ "stream/web",
13348
+ "string_decoder",
13349
+ "timers",
13350
+ "timers/promises",
13351
+ "url",
13352
+ "util",
13353
+ "zlib"
13354
+ ].flatMap((name) => [name, `node:${name}`])),
13355
+ platformSource: platformSource(nodejsEngineContract)
13356
+ };
13357
+ var currentContract = {
13358
+ ...nodejsContract,
13359
+ codeFetch: true,
13360
+ platformSource: platformSource(currentEngineContract)
13361
+ };
13362
+ function findEngineContract(contract) {
13363
+ if (contract == "open-flow-engine/v9") return currentContract;
13364
+ if (contract == "open-flow-engine/v8") return v8Contract;
13365
+ if (contract == "open-flow-engine/v8/nodejs-compat-v1") return nodejsContract;
13366
+ if (contract == "open-flow-engine/v7" || contract == "open-flow-engine/v7/nodejs-compat-v1") return {
13367
+ ...contract.endsWith("/nodejs-compat-v1") ? nodejsContract : v8Contract,
13368
+ workflowTools: false,
13369
+ httpRequests: false,
13370
+ platformSource: platformSource(contract)
13371
+ };
13372
+ if (contract == "open-flow-engine/v6" || contract == "open-flow-engine/v6/nodejs-compat-v1") return {
13373
+ ...contract == "open-flow-engine/v6" ? v8Contract : nodejsContract,
13374
+ workflowTools: false,
13375
+ httpRequests: false,
13376
+ waitAutoContinue: false,
13377
+ webhookResponses: false,
13378
+ platformSource: platformSource(contract)
13379
+ };
13380
+ }
13113
13381
  //#endregion
13114
13382
  //#region src/control/common/authoringLlm.ts
13115
13383
  var authoringLlmConfiguration = strictObject({
@@ -13696,6 +13964,7 @@ var authoringTypes = [
13696
13964
  "llm",
13697
13965
  "decision",
13698
13966
  "openapi",
13967
+ "http-request",
13699
13968
  "condition",
13700
13969
  "value",
13701
13970
  "wait",
@@ -13758,11 +14027,15 @@ var agentTool = union([workflowAgentToolSchema.omit({
13758
14027
  id: true,
13759
14028
  inputs: true
13760
14029
  }).extend({ inputs: toolSources }).strict()]);
13761
- var authoringCapabilities = array(union([connectorCapabilitySchema, strictObject({
13762
- kind: literal("workflow"),
13763
- name: id$1,
13764
- flowId: id$1
13765
- })]));
14030
+ var authoringCapabilities = array(union([
14031
+ connectorCapabilitySchema,
14032
+ strictObject({
14033
+ kind: literal("workflow"),
14034
+ name: id$1,
14035
+ flowId: id$1
14036
+ }),
14037
+ httpCapabilitySchema
14038
+ ]));
13766
14039
  var notification = strictObject({
13767
14040
  ...authoringDefinitionSchemas.connector.shape,
13768
14041
  messageHandle: id$1,
@@ -13822,6 +14095,7 @@ var authoringConfigurations = {
13822
14095
  }),
13823
14096
  "connector": authoringDefinitionSchemas.connector.omit({ outputMode: true }).strict(),
13824
14097
  "openapi": authoringOpenApiSchema,
14098
+ "http-request": httpRequestConfigSchema,
13825
14099
  "agent": authoringDefinitionSchemas.agent.omit({
13826
14100
  prompt: true,
13827
14101
  tools: true
@@ -14023,6 +14297,7 @@ var requestContracts = {
14023
14297
  examples: [{ revisionId: "REVISION" }]
14024
14298
  }
14025
14299
  };
14300
+ var codeGuidance = `Code is an ES module whose default export receives (inputs, context) and returns the business outputs. It may import the Node builtins ${[...findEngineContract(currentEngineContract).builtinModules].filter((name) => !name.startsWith("node:")).join(", ")}, with or without the node: prefix; fs is a fresh in-memory filesystem containing /tmp per execution. require, dynamic import, packages and the http/net builtins are unavailable. To call HTTP APIs, declare their hosts in config.capabilities as {kind: "http", hosts: ["api.example.com", "*.example.org"]} and use context.fetch(url, {method, headers, body}); it returns status, ok, headers.get(), text(), json() and bytes(), does not follow redirects, adds no credentials, and limits bodies to 1 MiB. Prefer an HTTP Request node for a single call without transformation and Connector Actions for services with accounts. context provides inputs, signal, getPrevious(), fetch, actions, workflows, artifact, flowId, runId and blockId. 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.`;
14026
14301
  /** Transport-independent discovery of the same requests the service validates. */
14027
14302
  function authoringRequestContract(name) {
14028
14303
  if (!Object.hasOwn(requestContracts, name)) return void 0;
@@ -14070,21 +14345,21 @@ function authoringSchema(kind) {
14070
14345
  "wait",
14071
14346
  "approval"
14072
14347
  ].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.",
14348
+ 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" ? codeGuidance : "Supply business configuration and input data. Fixed definitions are assembled by the tool. Existing constraints and defaults are preserved on partial updates.",
14074
14349
  example: {
14075
14350
  op: "node.add",
14076
14351
  as: "step",
14077
14352
  type: kind,
14078
14353
  name: "Step",
14079
14354
  ...{
14080
- start: { config: { inputDefs: {} } },
14081
- outputs: { config: { outputDefs: {} } },
14082
- workflow: { config: { flowId: "<Flow ID>" } },
14083
- connector: { config: {
14355
+ "start": { config: { inputDefs: {} } },
14356
+ "outputs": { config: { outputDefs: {} } },
14357
+ "workflow": { config: { flowId: "<Flow ID>" } },
14358
+ "connector": { config: {
14084
14359
  action: "<Action ID>",
14085
14360
  connectionId: "<Connection ID>"
14086
14361
  } },
14087
- poll: { config: {
14362
+ "poll": { config: {
14088
14363
  key: "<Trigger key>",
14089
14364
  schedule: [{
14090
14365
  type: "every",
@@ -14092,20 +14367,27 @@ function authoringSchema(kind) {
14092
14367
  value: 5
14093
14368
  }]
14094
14369
  } },
14095
- integration: { config: { key: "<Trigger key>" } },
14096
- openapi: { config: {
14370
+ "integration": { config: { key: "<Trigger key>" } },
14371
+ "http-request": {
14372
+ config: {},
14373
+ inputs: { url: {
14374
+ kind: "value",
14375
+ value: "https://example.com"
14376
+ } }
14377
+ },
14378
+ "openapi": { config: {
14097
14379
  sourceUrl: "https://example.com/openapi.json",
14098
14380
  path: "/items",
14099
14381
  method: "get"
14100
14382
  } },
14101
- code: {
14383
+ "code": {
14102
14384
  code: "export default ({value}) => ({result:value})",
14103
14385
  inputs: { value: {
14104
14386
  kind: "value",
14105
14387
  value: "Hello"
14106
14388
  } }
14107
14389
  },
14108
- condition: { config: {
14390
+ "condition": { config: {
14109
14391
  match: "first",
14110
14392
  branches: [{
14111
14393
  name: "yes",
@@ -14122,32 +14404,32 @@ function authoringSchema(kind) {
14122
14404
  }
14123
14405
  }]
14124
14406
  } },
14125
- value: { config: { values: {
14407
+ "value": { config: { values: {
14126
14408
  threshold: 100,
14127
14409
  region: "EU"
14128
14410
  } } },
14129
- webhook: { config: {
14411
+ "webhook": { config: {
14130
14412
  method: "POST",
14131
14413
  body: { orderId: {
14132
14414
  schema: { type: "string" },
14133
14415
  nullable: false
14134
14416
  } }
14135
14417
  } },
14136
- wait: {
14418
+ "wait": {
14137
14419
  prompt: "Continue processing this order?",
14138
14420
  inputs: { order: {
14139
14421
  kind: "value",
14140
14422
  value: { orderId: "A-1" }
14141
14423
  } }
14142
14424
  },
14143
- approval: {
14425
+ "approval": {
14144
14426
  prompt: "Approve this order?",
14145
14427
  inputs: { order: {
14146
14428
  kind: "value",
14147
14429
  value: { orderId: "A-1" }
14148
14430
  } }
14149
14431
  },
14150
- llm: {
14432
+ "llm": {
14151
14433
  config: {
14152
14434
  model: { model: "deepseek-v4-flash" },
14153
14435
  template: [{
@@ -14163,7 +14445,7 @@ function authoringSchema(kind) {
14163
14445
  }
14164
14446
  } }
14165
14447
  },
14166
- agent: {
14448
+ "agent": {
14167
14449
  config: { model: "deepseek-v4-flash" },
14168
14450
  inputs: { orders: {
14169
14451
  kind: "value",
@@ -14353,6 +14635,11 @@ function nodeSystemOutputPorts(node) {
14353
14635
  nullable: true
14354
14636
  } } : {};
14355
14637
  }
14638
+ //#endregion
14639
+ //#region src/flow/common/model.ts
14640
+ function portsByHandle(ports) {
14641
+ return Object.fromEntries(ports.flatMap((port) => "handle" in port ? [[port.handle, port]] : []));
14642
+ }
14356
14643
  function resourceNameIssue(value) {
14357
14644
  const name = value.trim();
14358
14645
  if (name.length == 0) return "empty";
@@ -14363,9 +14650,6 @@ function resourceNameIssue(value) {
14363
14650
  }
14364
14651
  if (!/^[\p{L}\p{N}](?:[\p{L}\p{N} _-]*[\p{L}\p{N}])?$/u.test(name)) return "specialCharacter";
14365
14652
  }
14366
- function portsByHandle(ports) {
14367
- return Object.fromEntries(ports.flatMap((port) => "handle" in port ? [[port.handle, port]] : []));
14368
- }
14369
14653
  var workflowToolNamePattern = /^[A-Za-z][A-Za-z0-9_-]{0,63}$/;
14370
14654
  function workflowToolNameIssue(name, otherNames = []) {
14371
14655
  if (!workflowToolNamePattern.test(name)) return "invalid";
@@ -14381,6 +14665,8 @@ function decodeTaskCapabilities(value) {
14381
14665
  if (workflowToolNameIssue(item.name, names)) throw new TypeError("Workflow tool names must be unique provider-compatible names.");
14382
14666
  names.add(item.name);
14383
14667
  }
14668
+ const http = parsed.filter((item) => item.kind == "http");
14669
+ if (http.length > 1 || http.some((item) => new Set(item.hosts).size != item.hosts.length)) throw new TypeError("Code declares HTTP hosts once, without duplicates.");
14384
14670
  let connectorIndex = 0;
14385
14671
  return parsed.map((item) => item.kind == "connector" ? connectors[connectorIndex++] : item);
14386
14672
  }
@@ -14516,10 +14802,10 @@ function upgradeRevisionContent(content) {
14516
14802
  function upgradeDecodedRevisionContent(content) {
14517
14803
  const graph = content.document.graph;
14518
14804
  const hasManual = Object.values(graph.nodes).some((node) => node.kind == "manual");
14519
- if (!hasManual && content.modelVersion == 11) return content;
14805
+ if (!hasManual && content.modelVersion == 12) return content;
14520
14806
  return {
14521
14807
  ...content,
14522
- modelVersion: 11,
14808
+ modelVersion: 12,
14523
14809
  document: {
14524
14810
  ...content.document,
14525
14811
  graph: hasManual ? {
@@ -14554,7 +14840,7 @@ function invalid(message) {
14554
14840
  throw new FlowChangeError(message);
14555
14841
  }
14556
14842
  function applyFlowChanges(content, operations) {
14557
- const source = content.modelVersion != 11 || Object.values(content.document.graph.nodes).some((node) => node.kind == "manual") ? decodeRevisionContent(content) : content;
14843
+ const source = content.modelVersion != 12 || Object.values(content.document.graph.nodes).some((node) => node.kind == "manual") ? decodeRevisionContent(content) : content;
14558
14844
  const document = { ...source.document };
14559
14845
  const modules = { ...source.modules };
14560
14846
  for (const operation of operations) switch (operation.kind) {
@@ -14999,10 +15285,10 @@ function applyFlowChanges(content, operations) {
14999
15285
  break;
15000
15286
  }
15001
15287
  }
15002
- assertOpenApiAuthBindings(document);
15288
+ assertDocumentHttpAuthBindings(document);
15003
15289
  return upgradeDecodedRevisionContent({
15004
15290
  document,
15005
- modelVersion: 11,
15291
+ modelVersion: 12,
15006
15292
  modules
15007
15293
  });
15008
15294
  }
@@ -15266,42 +15552,6 @@ async function imports(source) {
15266
15552
  }
15267
15553
  }
15268
15554
  //#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
15555
  //#region src/flow/common/nodeChanges.ts
15306
15556
  var codeTaskTemplate = `export default async function (inputs, context) {
15307
15557
  return { result: inputs.value }
@@ -16263,7 +16513,10 @@ function authoringNode(content, ref) {
16263
16513
  inputs: fieldsView([...task.inputs, ...node.kind == "task" ? node.additionalInputs ?? [] : []].filter((port) => !("handle" in port) || !llmReservedInputs.includes(port.handle)))
16264
16514
  };
16265
16515
  else if (task.executor.kind == "workflow") config = { flowId: task.executor.flowId };
16266
- else if (task.executor.kind == "openapi") config = { ...openApiConfigView(task.executor) };
16516
+ else if (task.executor.kind == "http-request") {
16517
+ const { kind: _kind, ...settings } = task.executor;
16518
+ config = settings;
16519
+ } else if (task.executor.kind == "openapi") config = { ...openApiConfigView(task.executor) };
16267
16520
  } else if (node.kind == "task" && "moduleId" in node.task) {
16268
16521
  config = {
16269
16522
  inputs: fieldsView([...node.task.inputs, ...node.additionalInputs ?? []]),
@@ -16564,7 +16817,7 @@ async function compileAuthoring(base, request, host) {
16564
16817
  const timing = record(record(patch.config).autoContinue);
16565
16818
  if (Object.hasOwn(timing, "kind") && timing.kind != record(record(view.config).autoContinue).kind) record(update.config).autoContinue = timing;
16566
16819
  }
16567
- if (type == "openapi" && Object.hasOwn(record(patch.config), "authentication")) record(update.config).authentication = record(patch.config).authentication;
16820
+ if ((type == "openapi" || type == "http-request") && Object.hasOwn(record(patch.config), "authentication")) record(update.config).authentication = record(patch.config).authentication;
16568
16821
  for (const path of clear) clearPath(update, path);
16569
16822
  if (typeof update.name != "string") fail("node.name-required", "Node name cannot be cleared.");
16570
16823
  const config = authoringConfigurations[type].parse(update.config);
@@ -16650,7 +16903,13 @@ async function compileAuthoring(base, request, host) {
16650
16903
  };
16651
16904
  } else task = await connectorTask(config, String(update.name));
16652
16905
  } else if (type == "decision") task = decisionTask(config.questions, String(update.name));
16653
- else if (type == "openapi") task = await prepareOpenApiTask(config, before, (url) => host.openapi(url), String(update.name), {
16906
+ else if (type == "http-request") {
16907
+ task = httpRequestTask(httpRequestConfigSchema.parse(config), String(update.name), before);
16908
+ next = {
16909
+ ...next,
16910
+ inputs: httpRequestInputs(node.inputs, before, task)
16911
+ };
16912
+ } else if (type == "openapi") task = await prepareOpenApiTask(config, before, (url) => host.openapi(url), String(update.name), {
16654
16913
  authentication: explicit("authentication"),
16655
16914
  serverUrl: explicit("serverUrl")
16656
16915
  });
@@ -16991,6 +17250,9 @@ async function compileAuthoring(base, request, host) {
16991
17250
  case "connector":
16992
17251
  changes = createManagedTask(identity, await connectorTask(config, name));
16993
17252
  break;
17253
+ case "http-request":
17254
+ changes = createManagedTask(identity, httpRequestTask(httpRequestConfigSchema.parse(config), name));
17255
+ break;
16994
17256
  case "openapi":
16995
17257
  changes = createManagedTask(identity, await prepareOpenApiTask(authoringConfigurations.openapi.parse(config), void 0, (url) => host.openapi(url), name));
16996
17258
  break;
@@ -17209,6 +17471,7 @@ var descriptions = {
17209
17471
  "poll": "Gmail polling by key; replace CONNECTION_ID with an active Gmail connection.",
17210
17472
  "integration": "Telegram webhook integration by key; replace CONNECTION_ID with an active Telegram connection.",
17211
17473
  "decision": "AI Decision evaluates named questions against target and returns a complete answer object per output. Configure target before running.",
17474
+ "http-request": "A single HTTP request. Bind url and request inputs; outputs are body, statusCode and headers.",
17212
17475
  "openapi": "A fixed JSON API operation. Replace the example document and URL before running.",
17213
17476
  "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
17477
  "code": "A JavaScript module and its node. Use Code for custom computation; use Connector Tasks for existing actions.",
@@ -17252,6 +17515,17 @@ function authoringExample(name) {
17252
17515
  instructions: "Does the customer need support?"
17253
17516
  }]);
17254
17517
  break;
17518
+ case "http-request":
17519
+ operations = [...createManagedTask({ nodeId: "http" }, httpRequestTask()), {
17520
+ kind: "graph.node.input.set",
17521
+ nodeId: "http",
17522
+ handle: "url",
17523
+ value: {
17524
+ kind: "value",
17525
+ value: "https://example.com"
17526
+ }
17527
+ }];
17528
+ break;
17255
17529
  case "openapi":
17256
17530
  operations = createManagedTask({ nodeId: "api" }, openApiTask(selectOperation({
17257
17531
  openapi: "3.1.0",