@oomol-lab/open-flow 0.1.0-beta.75 → 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 (125) hide show
  1. package/README.md +2 -1
  2. package/dist/browser/{ContentIcon-FCpKiwjp.js → ContentIcon-Cm1hbVzW.js} +2 -2
  3. package/dist/browser/{FlowCanvas-dzRBnlUT.js → FlowCanvas-NzKtla_c.js} +62 -62
  4. package/dist/browser/{createResourceDialog-BeYDdUl-.js → createResourceDialog-BgdedQqu.js} +3 -3
  5. package/dist/browser/{dialog-ZtpsFbl4.js → dialog-aSElFFw2.js} +49 -24
  6. package/dist/browser/{exportSvg-DqXw1yf-.js → exportSvg-Dcz4HTo_.js} +2 -2
  7. package/dist/browser/{flowChanges-b_5UobFj.js → flowChanges-NZyS7HSp.js} +207 -396
  8. package/dist/browser/{flowWorkspace-ItojZbO4.js → flowWorkspace-Bl0SDehy.js} +90 -13
  9. package/dist/browser/preview.css +515 -649
  10. package/dist/browser/preview.js +454 -545
  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 +515 -649
  17. package/dist/browser/workbench.js +7 -7
  18. package/dist/browser/{workbenchSelect-M441Lz0d.js → workbenchSelect-DBGP7Y4Z.js} +2 -2
  19. package/dist/command/index.js +33 -35
  20. package/dist/common/authoring.d.ts +3 -3
  21. package/dist/common/authoringSchema.d.ts +3 -0
  22. package/dist/common/connector-proxy.d.ts +1 -1
  23. package/dist/common/control-api-conformance.js +197 -136
  24. package/dist/common/control-api.d.ts +3 -2
  25. package/dist/common/control-api.js +192 -131
  26. package/dist/common/control-requests.js +126 -24
  27. package/dist/common/cron-trigger.d.ts +2 -1
  28. package/dist/common/decision.d.ts +4 -4
  29. package/dist/common/decision.js +5 -2
  30. package/dist/common/engine-contract.d.ts +5 -1
  31. package/dist/common/event-source-definition.d.ts +1 -1
  32. package/dist/common/event-source-view.d.ts +22 -0
  33. package/dist/common/event-source.d.ts +1 -1
  34. package/dist/common/event-source.js +24 -65
  35. package/dist/common/event-sources.d.ts +0 -21
  36. package/dist/common/flow-authoring.js +40 -18
  37. package/dist/common/flow-change-schema.d.ts +9 -1
  38. package/dist/common/flow-change.d.ts +7 -201
  39. package/dist/common/flow-change.js +46 -22
  40. package/dist/common/flow-encoding.js +40 -20
  41. package/dist/common/flow-input-value.d.ts +1 -1
  42. package/dist/common/flow-model.d.ts +121 -0
  43. package/dist/common/flow-notifications.d.ts +1 -1
  44. package/dist/common/flow-retry.d.ts +2 -4
  45. package/dist/common/flow-semantics.js +83 -86
  46. package/dist/common/flow-workflowReferences.d.ts +8 -0
  47. package/dist/common/flowInspection.d.ts +1 -1
  48. package/dist/common/http-hosts.d.ts +6 -0
  49. package/dist/common/http-request.d.ts +13 -5
  50. package/dist/common/http-request.js +23 -5
  51. package/dist/common/integration-trigger.d.ts +2 -1
  52. package/dist/common/mcp.js +195 -134
  53. package/dist/common/openapi.d.ts +4 -4
  54. package/dist/common/openapi.js +4 -1
  55. package/dist/common/poll-trigger.d.ts +2 -1
  56. package/dist/common/runtime-contract.d.ts +23 -1
  57. package/dist/common/runtime-contract.js +604 -72
  58. package/dist/common/runtime-nodejs-compat.d.ts +44 -0
  59. package/dist/common/runtime-nodejs-compat.js +5870 -0
  60. package/dist/common/scheduler-checkpoint.d.ts +1 -1
  61. package/dist/common/scheduler-node-execution.d.ts +1 -1
  62. package/dist/common/scheduler.d.ts +1 -1
  63. package/dist/common/scheduler.js +25 -4
  64. package/dist/common/trigger-catalog.d.ts +1 -7
  65. package/dist/common/trigger-config-options.d.ts +1 -1
  66. package/dist/common/trigger-config.d.ts +1 -1
  67. package/dist/common/trigger-contract.d.ts +2 -1
  68. package/dist/common/trigger-localization.d.ts +8 -2
  69. package/dist/common/trigger-model.d.ts +101 -0
  70. package/dist/common/webhook-response.d.ts +1 -1
  71. package/dist/common/webhook-trigger.d.ts +3 -1
  72. package/dist/common/workflow.d.ts +3 -12
  73. package/dist/common/workflow.js +25 -23
  74. package/dist/index.d.ts +41 -14
  75. package/package.json +5 -1
  76. package/src/base/common/json.ts +1 -1
  77. package/src/connector/common/proxy.ts +1 -1
  78. package/src/control/common/api.ts +6 -5
  79. package/src/control/common/authoringSchema.ts +9 -2
  80. package/src/control/common/authoringTools.ts +1 -1
  81. package/src/control/common/conformance.ts +1 -1
  82. package/src/control/common/connectorDecoders.ts +1 -1
  83. package/src/control/common/eventSources.ts +2 -29
  84. package/src/control/common/triggerCatalog.ts +1 -8
  85. package/src/decision/common/decision.ts +15 -7
  86. package/src/event-source/common/definition.ts +1 -1
  87. package/src/event-source/common/index.ts +1 -1
  88. package/src/event-source/common/view.ts +20 -0
  89. package/src/execution/common/checkpoint.ts +1 -1
  90. package/src/execution/common/node-execution.ts +1 -1
  91. package/src/execution/common/scheduler.ts +1 -1
  92. package/src/flow/common/change.ts +58 -192
  93. package/src/flow/common/changeSchema.ts +29 -4
  94. package/src/flow/common/connectionUsage.ts +1 -1
  95. package/src/flow/common/inputValue.ts +1 -1
  96. package/src/flow/common/model.ts +130 -0
  97. package/src/flow/common/modules.ts +1 -1
  98. package/src/flow/common/portChanges.ts +1 -1
  99. package/src/flow/common/retry.ts +2 -4
  100. package/src/flow/common/semantics.ts +11 -4
  101. package/src/flow/common/webhookResponse.ts +1 -1
  102. package/src/flow/common/workflowReferences.ts +31 -0
  103. package/src/http/common/authBindings.ts +6 -9
  104. package/src/http/common/hosts.ts +13 -0
  105. package/src/http/common/httpRequest.ts +30 -15
  106. package/src/openapi/common/openapi.ts +9 -5
  107. package/src/{execution → runtime}/common/engineContract.ts +20 -15
  108. package/src/runtime/common/nodejsCompat.ts +275 -0
  109. package/src/runtime/common/nodejsGuest.generated.json +47 -0
  110. package/src/runtime/common/runtime.ts +1138 -0
  111. package/src/trigger/common/config.ts +1 -1
  112. package/src/trigger/common/configOptions.ts +1 -1
  113. package/src/trigger/common/contract.ts +2 -1
  114. package/src/trigger/common/cron.ts +2 -1
  115. package/src/trigger/common/integration.ts +2 -1
  116. package/src/trigger/common/model.ts +87 -0
  117. package/src/trigger/common/poll.ts +2 -1
  118. package/src/trigger/common/webhook.ts +3 -1
  119. package/src/trigger/providers/fieldDescriptions.ts +1 -1
  120. package/src/trigger/providers/localization.ts +9 -2
  121. package/src/trigger/providers/remote.ts +1 -1
  122. package/src/types/index.ts +44 -15
  123. package/src/workflow/common/workflow.ts +3 -44
  124. package/src/execution/common/runtime.ts +0 -563
  125. /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;
@@ -12286,12 +12289,17 @@ function decisionTask(questions = [defaultDecisionQuestion()], name = "AI Decisi
12286
12289
  }
12287
12290
  //#endregion
12288
12291
  //#region src/http/common/authBindings.ts
12289
- /** Never allow credentials to enter a Revision as literal node inputs. */
12290
- function assertHttpAuthBindings(document) {
12291
- for (const node of Object.values(document.graph.nodes)) {
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
- }
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("."));
12295
12303
  }
12296
12304
  //#endregion
12297
12305
  //#region src/flow/common/portChanges.ts
@@ -12665,7 +12673,15 @@ var workflowCapabilitySchema = strictObject({
12665
12673
  inputs: array(port),
12666
12674
  outputs: array(port).nullable()
12667
12675
  });
12668
- 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
+ ]);
12669
12685
  var inline = object$1({
12670
12686
  ...ports,
12671
12687
  name: text$1,
@@ -13045,7 +13061,8 @@ var revision = object$1({
13045
13061
  literal(8),
13046
13062
  literal(9),
13047
13063
  literal(10),
13048
- literal(11)
13064
+ literal(11),
13065
+ literal(12)
13049
13066
  ]),
13050
13067
  document,
13051
13068
  modules: record$3(text$1, module)
@@ -13076,7 +13093,7 @@ function decodeRevisionContent(value) {
13076
13093
  checkJsonDepth(value);
13077
13094
  const content = revision.parse(value);
13078
13095
  checkModelVersion(content);
13079
- assertHttpAuthBindings(content.document);
13096
+ assertDocumentHttpAuthBindings(content.document);
13080
13097
  return content;
13081
13098
  }
13082
13099
  var shapes = {
@@ -13270,6 +13287,7 @@ function changeOperationsSchema(kind) {
13270
13287
  return toJSONSchema(schema, { io: "input" });
13271
13288
  }
13272
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.");
13273
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.");
13274
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.");
13275
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.");
@@ -13285,6 +13303,81 @@ function checkModelVersion(content) {
13285
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.");
13286
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.");
13287
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
+ }
13288
13381
  //#endregion
13289
13382
  //#region src/control/common/authoringLlm.ts
13290
13383
  var authoringLlmConfiguration = strictObject({
@@ -13934,11 +14027,15 @@ var agentTool = union([workflowAgentToolSchema.omit({
13934
14027
  id: true,
13935
14028
  inputs: true
13936
14029
  }).extend({ inputs: toolSources }).strict()]);
13937
- var authoringCapabilities = array(union([connectorCapabilitySchema, strictObject({
13938
- kind: literal("workflow"),
13939
- name: id$1,
13940
- flowId: id$1
13941
- })]));
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
+ ]));
13942
14039
  var notification = strictObject({
13943
14040
  ...authoringDefinitionSchemas.connector.shape,
13944
14041
  messageHandle: id$1,
@@ -14200,6 +14297,7 @@ var requestContracts = {
14200
14297
  examples: [{ revisionId: "REVISION" }]
14201
14298
  }
14202
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.`;
14203
14301
  /** Transport-independent discovery of the same requests the service validates. */
14204
14302
  function authoringRequestContract(name) {
14205
14303
  if (!Object.hasOwn(requestContracts, name)) return void 0;
@@ -14247,7 +14345,7 @@ function authoringSchema(kind) {
14247
14345
  "wait",
14248
14346
  "approval"
14249
14347
  ].includes(kind),
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.",
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.",
14251
14349
  example: {
14252
14350
  op: "node.add",
14253
14351
  as: "step",
@@ -14537,6 +14635,11 @@ function nodeSystemOutputPorts(node) {
14537
14635
  nullable: true
14538
14636
  } } : {};
14539
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
+ }
14540
14643
  function resourceNameIssue(value) {
14541
14644
  const name = value.trim();
14542
14645
  if (name.length == 0) return "empty";
@@ -14547,9 +14650,6 @@ function resourceNameIssue(value) {
14547
14650
  }
14548
14651
  if (!/^[\p{L}\p{N}](?:[\p{L}\p{N} _-]*[\p{L}\p{N}])?$/u.test(name)) return "specialCharacter";
14549
14652
  }
14550
- function portsByHandle(ports) {
14551
- return Object.fromEntries(ports.flatMap((port) => "handle" in port ? [[port.handle, port]] : []));
14552
- }
14553
14653
  var workflowToolNamePattern = /^[A-Za-z][A-Za-z0-9_-]{0,63}$/;
14554
14654
  function workflowToolNameIssue(name, otherNames = []) {
14555
14655
  if (!workflowToolNamePattern.test(name)) return "invalid";
@@ -14565,6 +14665,8 @@ function decodeTaskCapabilities(value) {
14565
14665
  if (workflowToolNameIssue(item.name, names)) throw new TypeError("Workflow tool names must be unique provider-compatible names.");
14566
14666
  names.add(item.name);
14567
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.");
14568
14670
  let connectorIndex = 0;
14569
14671
  return parsed.map((item) => item.kind == "connector" ? connectors[connectorIndex++] : item);
14570
14672
  }
@@ -14700,10 +14802,10 @@ function upgradeRevisionContent(content) {
14700
14802
  function upgradeDecodedRevisionContent(content) {
14701
14803
  const graph = content.document.graph;
14702
14804
  const hasManual = Object.values(graph.nodes).some((node) => node.kind == "manual");
14703
- if (!hasManual && content.modelVersion == 11) return content;
14805
+ if (!hasManual && content.modelVersion == 12) return content;
14704
14806
  return {
14705
14807
  ...content,
14706
- modelVersion: 11,
14808
+ modelVersion: 12,
14707
14809
  document: {
14708
14810
  ...content.document,
14709
14811
  graph: hasManual ? {
@@ -14738,7 +14840,7 @@ function invalid(message) {
14738
14840
  throw new FlowChangeError(message);
14739
14841
  }
14740
14842
  function applyFlowChanges(content, operations) {
14741
- 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;
14742
14844
  const document = { ...source.document };
14743
14845
  const modules = { ...source.modules };
14744
14846
  for (const operation of operations) switch (operation.kind) {
@@ -15183,10 +15285,10 @@ function applyFlowChanges(content, operations) {
15183
15285
  break;
15184
15286
  }
15185
15287
  }
15186
- assertHttpAuthBindings(document);
15288
+ assertDocumentHttpAuthBindings(document);
15187
15289
  return upgradeDecodedRevisionContent({
15188
15290
  document,
15189
- modelVersion: 11,
15291
+ modelVersion: 12,
15190
15292
  modules
15191
15293
  });
15192
15294
  }
@@ -1,4 +1,5 @@
1
- import type { JsonValue, TriggerSchedule } from './flow-change.js';
1
+ import type { JsonValue } from './flow-model.js';
2
+ import type { TriggerSchedule } from './trigger-model.js';
2
3
  export declare function validateTriggerSchedule(rules: readonly TriggerSchedule[]): void;
3
4
  export declare function validateCronExpression(expression: string, timezone: string): void;
4
5
  export declare function nextTriggerScheduledAt(rules: readonly TriggerSchedule[], afterMs: number): number;
@@ -1,4 +1,4 @@
1
- import type { JsonValue, ManagedTaskDefinition } from './flow-change.js';
1
+ import type { JsonValue, ManagedTaskDefinitionOf, TaskExecutor } from './flow-model.js';
2
2
  export type DecisionQuestion = {
3
3
  readonly name: string;
4
4
  readonly instructions: string;
@@ -36,12 +36,12 @@ export declare const decisionLimits: {
36
36
  export declare function limitDecisionQuestion(question: DecisionQuestion): DecisionQuestion;
37
37
  export declare function limitDecisionQuestions(questions: readonly DecisionQuestion[]): readonly DecisionQuestion[];
38
38
  /** Loading an oversized task also updates its previously generated output schemas. */
39
- export declare function limitDecisionTask(task: ManagedTaskDefinition): ManagedTaskDefinition;
39
+ export declare function limitDecisionTask<Task extends ManagedTaskDefinitionOf<TaskExecutor>>(task: Task): Task;
40
40
  export declare const decisionStateSchema: JsonValue;
41
41
  export declare const defaultDecisionQuestion: (name?: string) => DecisionQuestion;
42
42
  export declare function decisionQuestionIssues(questions: readonly DecisionQuestion[]): readonly DecisionIssue[];
43
43
  export declare function decisionAnswerSchema(question: DecisionQuestion): JsonValue;
44
- export declare function decisionTask(questions?: readonly DecisionQuestion[], name?: string): ManagedTaskDefinition;
45
- export declare function decisionTaskIssues(task: ManagedTaskDefinition): readonly DecisionIssue[];
44
+ export declare function decisionTask(questions?: readonly DecisionQuestion[], name?: string): ManagedTaskDefinitionOf<DecisionExecutor>;
45
+ export declare function decisionTaskIssues(task: ManagedTaskDefinitionOf<TaskExecutor>): readonly DecisionIssue[];
46
46
  export declare function decisionRequest(questions: readonly DecisionQuestion[], state: JsonValue): JsonValue;
47
47
  export declare function decisionAnswers(questions: readonly DecisionQuestion[], response: unknown): Readonly<Record<string, JsonValue>>;
@@ -3686,6 +3686,9 @@ function schemaValidationErrors(value, schema) {
3686
3686
  }
3687
3687
  //#endregion
3688
3688
  //#region src/decision/common/decision.ts
3689
+ function isDecisionExecutor(executor) {
3690
+ return executor.kind === "decision";
3691
+ }
3689
3692
  var decisionModel = "typesafe/jev";
3690
3693
  var decisionLimits = {
3691
3694
  choice: 255,
@@ -3709,7 +3712,7 @@ function limitDecisionQuestions(questions) {
3709
3712
  }
3710
3713
  /** Loading an oversized task also updates its previously generated output schemas. */
3711
3714
  function limitDecisionTask(task) {
3712
- if (task.executor.kind !== "decision") return task;
3715
+ if (!isDecisionExecutor(task.executor)) return task;
3713
3716
  const original = task.executor.questions;
3714
3717
  const questions = limitDecisionQuestions(original);
3715
3718
  if (questions === original) return task;
@@ -3834,7 +3837,7 @@ function decisionTask(questions = [defaultDecisionQuestion()], name = "AI Decisi
3834
3837
  }
3835
3838
  function decisionTaskIssues(task) {
3836
3839
  task = limitDecisionTask(task);
3837
- if (task.executor.kind !== "decision") return [];
3840
+ if (!isDecisionExecutor(task.executor)) return [];
3838
3841
  const expected = decisionTask(task.executor.questions, task.name);
3839
3842
  return [...decisionQuestionIssues(task.executor.questions), ...!dequal(task.inputs, expected.inputs) || !dequal(task.outputs, expected.outputs) ? [{
3840
3843
  field: "ports",
@@ -7,7 +7,11 @@ export interface EngineContract {
7
7
  readonly webhookResponses?: boolean;
8
8
  readonly workflowTools?: boolean;
9
9
  readonly httpRequests?: boolean;
10
+ /** Code may call `context.fetch` for hosts declared by its `http` Capability. */
11
+ readonly codeFetch?: boolean;
10
12
  }
11
- export declare const currentEngineContract = "open-flow-engine/v8";
13
+ /** v9 is a single contract: the Node compatibility builtins, `context.fetch`, and no `context.egress`. */
14
+ export declare const currentEngineContract = "open-flow-engine/v9";
15
+ /** The published v8 Node compatibility contract, retained for existing Publications and Runs. */
12
16
  export declare const nodejsEngineContract = "open-flow-engine/v8/nodejs-compat-v1";
13
17
  export declare function findEngineContract(contract: string): EngineContract | undefined;
@@ -1,4 +1,4 @@
1
- import type { JsonValue } from './flow-change.js';
1
+ import type { JsonValue } from '../index.js';
2
2
  export interface SourceConfiguration {
3
3
  readonly identity: string;
4
4
  readonly eventTypes: string[];
@@ -0,0 +1,22 @@
1
+ import { z } from 'zod';
2
+ /** Public projection of a source that Connector validates and Open Flow exposes unchanged. */
3
+ export declare const eventSourceViewSchema: z.ZodObject<{
4
+ appId: z.ZodNullable<z.ZodString>;
5
+ workspaceId: z.ZodOptional<z.ZodString>;
6
+ installationId: z.ZodOptional<z.ZodString>;
7
+ organizationId: z.ZodOptional<z.ZodString>;
8
+ projectId: z.ZodOptional<z.ZodString>;
9
+ projectKey: z.ZodOptional<z.ZodString>;
10
+ subscriptionStatus: z.ZodOptional<z.ZodEnum<{
11
+ error: "error";
12
+ idle: "idle";
13
+ pending: "pending";
14
+ ready: "ready";
15
+ }>>;
16
+ lastError: z.ZodOptional<z.ZodString>;
17
+ signingSecretConfigured: z.ZodOptional<z.ZodBoolean>;
18
+ manageSubscriptions: z.ZodNullable<z.ZodBoolean>;
19
+ verificationTokenConfigured: z.ZodNullable<z.ZodBoolean>;
20
+ encryptKeyConfigured: z.ZodNullable<z.ZodBoolean>;
21
+ verifiedAt: z.ZodNullable<z.ZodString>;
22
+ }, z.core.$strip>;
@@ -1,6 +1,6 @@
1
1
  import type { EventSourceDefinition, SourceConfiguration } from './event-source-definition.js';
2
2
  import { z } from 'zod';
3
- import { eventSourceViewSchema } from './event-sources.js';
3
+ import { eventSourceViewSchema } from './event-source-view.js';
4
4
  export type { EventSourceDefinition, SourceConfiguration, SourceEvent, SourceSubscription, SourceOperation, SourceReference, SourceReferenceOperation, } from './event-source-definition.js';
5
5
  export { SourceIdentityError } from './event-source-definition.js';
6
6
  export declare function eventSourceDefinition(kind: string): EventSourceDefinition;
@@ -5569,71 +5569,6 @@ function json(params) {
5569
5569
  return jsonSchema;
5570
5570
  }
5571
5571
  //#endregion
5572
- //#region src/control/common/eventSources.ts
5573
- var id = string().min(1).max(256);
5574
- var eventType = string().regex(/^[a-z][a-z0-9_.:]{0,127}$/);
5575
- var name = string().trim().min(1).max(128);
5576
- var eventSourceViewSchema = object({
5577
- version: literal(1),
5578
- sourceId: id,
5579
- revision: int().positive(),
5580
- name,
5581
- provider: _enum([
5582
- "feishu",
5583
- "feishu_app_bot",
5584
- "slackbot",
5585
- "intercom",
5586
- "sentry",
5587
- "zoom",
5588
- "fireflies",
5589
- "jira"
5590
- ]),
5591
- appId: id.nullable(),
5592
- workspaceId: id.optional(),
5593
- installationId: id.optional(),
5594
- organizationId: id.optional(),
5595
- projectId: id.optional(),
5596
- projectKey: id.optional(),
5597
- subscriptionStatus: _enum([
5598
- "idle",
5599
- "pending",
5600
- "ready",
5601
- "error"
5602
- ]).optional(),
5603
- lastError: string().optional(),
5604
- signingSecretConfigured: boolean().optional(),
5605
- connectionId: id,
5606
- teamId: id.nullable(),
5607
- enabled: boolean(),
5608
- eventTypes: array(eventType),
5609
- manageSubscriptions: boolean().nullable(),
5610
- verificationTokenConfigured: boolean().nullable(),
5611
- encryptKeyConfigured: boolean().nullable(),
5612
- endpointUrl: string().nullable(),
5613
- verifiedAt: string().nullable(),
5614
- lastReceivedAt: string().nullable(),
5615
- updatedAt: string(),
5616
- consumers: array(object({
5617
- flowId: id,
5618
- flowName: string(),
5619
- triggerNodeId: id
5620
- }))
5621
- }).pick({
5622
- appId: true,
5623
- workspaceId: true,
5624
- installationId: true,
5625
- organizationId: true,
5626
- projectId: true,
5627
- projectKey: true,
5628
- subscriptionStatus: true,
5629
- lastError: true,
5630
- signingSecretConfigured: true,
5631
- manageSubscriptions: true,
5632
- verificationTokenConfigured: true,
5633
- encryptKeyConfigured: true,
5634
- verifiedAt: true
5635
- });
5636
- //#endregion
5637
5572
  //#region src/event-source/common/catalog.generated.json
5638
5573
  var catalog_generated_default = [
5639
5574
  {
@@ -5704,6 +5639,30 @@ var catalog_generated_default = [
5704
5639
  //#region src/event-source/common/definition.ts
5705
5640
  var SourceIdentityError = class extends Error {};
5706
5641
  //#endregion
5642
+ //#region src/event-source/common/view.ts
5643
+ var id = string().min(1).max(256);
5644
+ /** Public projection of a source that Connector validates and Open Flow exposes unchanged. */
5645
+ var eventSourceViewSchema = object({
5646
+ appId: id.nullable(),
5647
+ workspaceId: id.optional(),
5648
+ installationId: id.optional(),
5649
+ organizationId: id.optional(),
5650
+ projectId: id.optional(),
5651
+ projectKey: id.optional(),
5652
+ subscriptionStatus: _enum([
5653
+ "idle",
5654
+ "pending",
5655
+ "ready",
5656
+ "error"
5657
+ ]).optional(),
5658
+ lastError: string().optional(),
5659
+ signingSecretConfigured: boolean().optional(),
5660
+ manageSubscriptions: boolean().nullable(),
5661
+ verificationTokenConfigured: boolean().nullable(),
5662
+ encryptKeyConfigured: boolean().nullable(),
5663
+ verifiedAt: string().nullable()
5664
+ });
5665
+ //#endregion
5707
5666
  //#region src/event-source/common/index.ts
5708
5667
  function eventSourceDefinition(kind) {
5709
5668
  for (const entry of catalog_generated_default) if (entry.kind === kind) return entry;
@@ -1,24 +1,3 @@
1
- import { z } from 'zod';
2
- export declare const eventSourceViewSchema: z.ZodObject<{
3
- appId: z.ZodNullable<z.ZodString>;
4
- workspaceId: z.ZodOptional<z.ZodString>;
5
- installationId: z.ZodOptional<z.ZodString>;
6
- organizationId: z.ZodOptional<z.ZodString>;
7
- projectId: z.ZodOptional<z.ZodString>;
8
- projectKey: z.ZodOptional<z.ZodString>;
9
- subscriptionStatus: z.ZodOptional<z.ZodEnum<{
10
- error: "error";
11
- idle: "idle";
12
- pending: "pending";
13
- ready: "ready";
14
- }>>;
15
- lastError: z.ZodOptional<z.ZodString>;
16
- signingSecretConfigured: z.ZodOptional<z.ZodBoolean>;
17
- manageSubscriptions: z.ZodNullable<z.ZodBoolean>;
18
- verificationTokenConfigured: z.ZodNullable<z.ZodBoolean>;
19
- encryptKeyConfigured: z.ZodNullable<z.ZodBoolean>;
20
- verifiedAt: z.ZodNullable<z.ZodString>;
21
- }, z.core.$strip>;
22
1
  export interface CreateFeishuEventSource {
23
2
  readonly kind?: 'feishu';
24
3
  readonly version: 1;