@oomol-lab/open-flow 0.1.0-beta.69 → 0.1.0-beta.70

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 (49) hide show
  1. package/dist/browser/{ContentIcon-CsECY5id.js → ContentIcon-CUQHjQIw.js} +16 -8
  2. package/dist/browser/{FlowCanvas-C5X22xQ7.js → FlowCanvas-CqtUDPGj.js} +11 -26
  3. package/dist/browser/{createResourceDialog-Di5BBrQv.js → createResourceDialog-BAHYW9yu.js} +3 -3
  4. package/dist/browser/{dialog-Bjo-r9B0.js → dialog-DcGOzUP2.js} +162 -12
  5. package/dist/browser/{exportSvg-Cj6Spxx-.js → exportSvg-Dv5Qgrq7.js} +2 -2
  6. package/dist/browser/flow-authoring.js +95 -12
  7. package/dist/browser/flow-change-schema.d.ts +24 -1
  8. package/dist/browser/flow-change.d.ts +33 -4
  9. package/dist/browser/flow-change.js +96 -13
  10. package/dist/browser/{flowChanges-Dp-rcEJ6.js → flowChanges-CYyehKer.js} +2593 -2254
  11. package/dist/browser/{flowWorkspace-CB1QACku.js → flowWorkspace-qYUZPJHR.js} +1114 -392
  12. package/dist/browser/preview.css +225 -221
  13. package/dist/browser/preview.js +3781 -2655
  14. package/dist/browser/{tooltip-CJjYs_2I.js → tooltip-wZJRB9oP.js} +28 -1
  15. package/dist/browser/ui.css +8 -20
  16. package/dist/browser/workbench.css +225 -221
  17. package/dist/browser/workbench.js +31 -10
  18. package/dist/browser/{workbenchSelect-C3hxUcYm.js → workbenchSelect-D8_vP2p5.js} +2 -2
  19. package/dist/command/index.js +45 -45
  20. package/dist/common/authoring.d.ts +3 -3
  21. package/dist/common/authoringExamples.d.ts +3 -2
  22. package/dist/common/authoringSchema.d.ts +37 -374
  23. package/dist/common/control-api-conformance.js +151 -55
  24. package/dist/common/control-api.d.ts +12 -78
  25. package/dist/common/control-api.js +162 -39
  26. package/dist/common/control-requests.d.ts +3 -3
  27. package/dist/common/control-requests.js +221 -35
  28. package/dist/common/decision.js +85 -7
  29. package/dist/common/engine-contract.d.ts +4 -2
  30. package/dist/common/flow-encoding.js +110 -14
  31. package/dist/common/flow-graph.d.ts +3 -0
  32. package/dist/common/flow-semantics.js +273 -14
  33. package/dist/common/integration-trigger.js +85 -7
  34. package/dist/common/liveDetails.d.ts +15 -0
  35. package/dist/common/mcp.d.ts +3 -3
  36. package/dist/common/mcp.js +134 -38
  37. package/dist/common/openapi.js +85 -7
  38. package/dist/common/poll-trigger.js +85 -7
  39. package/dist/common/run-events.d.ts +2 -0
  40. package/dist/common/run-events.js +59 -2
  41. package/dist/common/runtime-contract.js +14 -4
  42. package/dist/common/scheduler.d.ts +6 -2
  43. package/dist/common/scheduler.js +178 -11
  44. package/dist/common/webhook-response.d.ts +43 -0
  45. package/dist/common/webhook-trigger.d.ts +12 -0
  46. package/dist/common/webhook-trigger.js +236 -9
  47. package/dist/common/workflow.js +85 -7
  48. package/package.json +1 -1
  49. package/skills/open-flow/references/flow-authoring.md +15 -10
@@ -9656,10 +9656,10 @@ function upgradeRevisionContent(content) {
9656
9656
  function upgradeDecodedRevisionContent(content) {
9657
9657
  const graph = content.document.graph;
9658
9658
  const hasManual = Object.values(graph.nodes).some((node) => node.kind == "manual");
9659
- if (!hasManual && content.modelVersion == 9) return content;
9659
+ if (!hasManual && content.modelVersion == 10) return content;
9660
9660
  return {
9661
9661
  ...content,
9662
- modelVersion: 9,
9662
+ modelVersion: 10,
9663
9663
  document: {
9664
9664
  ...content.document,
9665
9665
  graph: hasManual ? {
@@ -9694,7 +9694,7 @@ function invalid(message) {
9694
9694
  throw new FlowChangeError(message);
9695
9695
  }
9696
9696
  function applyFlowChanges(content, operations) {
9697
- const source = content.modelVersion != 9 || Object.values(content.document.graph.nodes).some((node) => node.kind == "manual") ? decodeRevisionContent(content) : content;
9697
+ const source = content.modelVersion != 10 || Object.values(content.document.graph.nodes).some((node) => node.kind == "manual") ? decodeRevisionContent(content) : content;
9698
9698
  const document = { ...source.document };
9699
9699
  const modules = { ...source.modules };
9700
9700
  for (const operation of operations) switch (operation.kind) {
@@ -10010,12 +10010,15 @@ function applyFlowChanges(content, operations) {
10010
10010
  const node = graph.nodes[operation.nodeId];
10011
10011
  if (node?.kind != "wait" && node?.kind != "approval" || !dequal({
10012
10012
  inputDefinitions: node.inputDefinitions,
10013
- prompt: node.prompt
10013
+ prompt: node.prompt,
10014
+ ...node.kind == "wait" && node.autoContinue != null ? { autoContinue: node.autoContinue } : {}
10014
10015
  }, operation.before)) invalid("The resolution node changed before this operation was applied.");
10016
+ if (node.kind == "approval" && operation.value.autoContinue != null) invalid("Approval does not support automatic continuation.");
10015
10017
  const updated = {
10016
10018
  ...node,
10017
10019
  ...operation.value
10018
10020
  };
10021
+ if (updated.kind == "wait" && operation.value.autoContinue == null) Reflect.deleteProperty(updated, "autoContinue");
10019
10022
  document.graph = {
10020
10023
  ...graph,
10021
10024
  nodes: {
@@ -10139,7 +10142,7 @@ function applyFlowChanges(content, operations) {
10139
10142
  assertOpenApiAuthBindings(document);
10140
10143
  return upgradeDecodedRevisionContent({
10141
10144
  document,
10142
- modelVersion: 9,
10145
+ modelVersion: 10,
10143
10146
  modules
10144
10147
  });
10145
10148
  }
@@ -13071,6 +13074,33 @@ var triggerScheduleSchema = array(union([object$1({
13071
13074
  value: number()
13072
13075
  })]));
13073
13076
  //#endregion
13077
+ //#region src/localization/common/timeZone.ts
13078
+ /** Validate a named timezone using the same runtime data used for date conversion. */
13079
+ function isTimeZone(value) {
13080
+ try {
13081
+ Intl.DateTimeFormat("en", { timeZone: value });
13082
+ return true;
13083
+ } catch {
13084
+ return false;
13085
+ }
13086
+ }
13087
+ //#endregion
13088
+ //#region src/flow/common/wait.ts
13089
+ /** Drafts retain incomplete values; semantic validation gates publication and execution. */
13090
+ var waitAutoContinueDraftSchema = discriminatedUnion("kind", [strictObject({
13091
+ kind: literal("after"),
13092
+ durationMs: number().nullable()
13093
+ }), strictObject({
13094
+ kind: literal("at"),
13095
+ at: string(),
13096
+ timezone: string().optional()
13097
+ })]);
13098
+ /** Static business configuration; the deployment owns the allowed wait lifetime. */
13099
+ var waitAutoContinueSchema = discriminatedUnion("kind", [waitAutoContinueDraftSchema.options[0].extend({ durationMs: number().int().positive().max(Number.MAX_SAFE_INTEGER) }), waitAutoContinueDraftSchema.options[1].extend({
13100
+ at: datetime({ offset: true }),
13101
+ timezone: string().refine(isTimeZone, "Select a valid IANA timezone.").optional()
13102
+ })]);
13103
+ //#endregion
13074
13104
  //#region src/flow/common/webhookMethod.ts
13075
13105
  var webhookMethods = [
13076
13106
  "GET",
@@ -13082,6 +13112,44 @@ var webhookMethods = [
13082
13112
  function webhookSupportsBody(method) {
13083
13113
  return method !== "GET";
13084
13114
  }
13115
+ //#endregion
13116
+ //#region src/flow/common/webhookResponse.ts
13117
+ var webhookResponseTimeout = {
13118
+ defaultMs: 3e4,
13119
+ minMs: 1e3,
13120
+ maxMs: 6e4
13121
+ };
13122
+ /** Fixed inputs belong to the node, not author-supplied definitions. */
13123
+ var webhookResponseInputs = [
13124
+ {
13125
+ handle: "body",
13126
+ jsonSchema: {},
13127
+ nullable: true,
13128
+ value: ""
13129
+ },
13130
+ {
13131
+ handle: "statusCode",
13132
+ jsonSchema: { type: "number" },
13133
+ nullable: false,
13134
+ value: 200
13135
+ },
13136
+ {
13137
+ handle: "headers",
13138
+ jsonSchema: {
13139
+ jsonSchema: {
13140
+ type: "object",
13141
+ additionalProperties: { type: [
13142
+ "string",
13143
+ "number",
13144
+ "boolean"
13145
+ ] }
13146
+ },
13147
+ nullable: true
13148
+ }.jsonSchema,
13149
+ nullable: false,
13150
+ value: {}
13151
+ }
13152
+ ];
13085
13153
  var text$1 = string();
13086
13154
  var actionConnection = text$1.describe("Account selection: omit while unconfigured; use an account ID to select it; use \"\" to explicitly defer configuration. Deferred Actions fail if called; deferred Agent tools are excluded from the callable tool set. Not supported by Triggers.");
13087
13155
  var json$4 = json$5();
@@ -13309,9 +13377,24 @@ var webhookOptions = object$1({
13309
13377
  allowedMethods: never().optional(),
13310
13378
  allowedOrigins: strings.optional(),
13311
13379
  noResponseBody: never().optional(),
13380
+ responseBody: discriminatedUnion("kind", [strictObject({
13381
+ kind: literal("workflow-outputs"),
13382
+ output: text$1.optional(),
13383
+ timeoutMs: number().int().min(webhookResponseTimeout.minMs).max(webhookResponseTimeout.maxMs).optional()
13384
+ }), strictObject({
13385
+ kind: literal("webhook-response"),
13386
+ nodeId: text$1.optional(),
13387
+ timeoutMs: number().int().min(webhookResponseTimeout.minMs).max(webhookResponseTimeout.maxMs).optional()
13388
+ })]).optional(),
13312
13389
  responseData: text$1.optional(),
13313
13390
  responseHeaders: record$3(text$1, text$1).optional(),
13314
- responseStatusCode: number().int().min(200).max(599).optional()
13391
+ responseHeadersSource: strictObject({
13392
+ kind: literal("workflow-outputs"),
13393
+ output: text$1.optional()
13394
+ }).optional(),
13395
+ responseHeaderOutputs: record$3(text$1, text$1).optional(),
13396
+ responseStatusCode: number().int().min(200).max(599).optional(),
13397
+ responseStatusCodeOutput: text$1.optional()
13315
13398
  });
13316
13399
  var webhook = {
13317
13400
  bodyFields: array(input),
@@ -13366,6 +13449,12 @@ var base = {
13366
13449
  onError: _enum(["stop", "error"]).optional()
13367
13450
  };
13368
13451
  var node = union([
13452
+ strictObject({
13453
+ ...base,
13454
+ kind: literal("webhook-response"),
13455
+ retry: never().optional(),
13456
+ onError: never().optional()
13457
+ }),
13369
13458
  strictObject({
13370
13459
  ...base,
13371
13460
  kind: literal("outputs"),
@@ -13398,7 +13487,8 @@ var node = union([
13398
13487
  strictObject({
13399
13488
  ...base,
13400
13489
  kind: literal("wait"),
13401
- ...wait
13490
+ ...wait,
13491
+ autoContinue: waitAutoContinueDraftSchema.optional()
13402
13492
  }).omit({ timeoutMs: true }),
13403
13493
  object$1({
13404
13494
  ...trigger$1,
@@ -13454,6 +13544,7 @@ var authoringDefinitionSchemas = {
13454
13544
  ports,
13455
13545
  condition: strictObject(condition),
13456
13546
  wait: strictObject(wait),
13547
+ waitAutoContinue: waitAutoContinueSchema,
13457
13548
  webhook: strictObject(webhook),
13458
13549
  schedule: triggerScheduleSchema,
13459
13550
  capabilities: array(capability),
@@ -13500,7 +13591,8 @@ var revision = object$1({
13500
13591
  literal(6),
13501
13592
  literal(7),
13502
13593
  literal(8),
13503
- literal(9)
13594
+ literal(9),
13595
+ literal(10)
13504
13596
  ]),
13505
13597
  document,
13506
13598
  modules: record$3(text$1, module)
@@ -13633,8 +13725,14 @@ var shapes = {
13633
13725
  },
13634
13726
  "graph.node.resolution.set": {
13635
13727
  ...at,
13636
- before: object$1(wait),
13637
- value: object$1(wait)
13728
+ before: strictObject({
13729
+ ...wait,
13730
+ autoContinue: waitAutoContinueDraftSchema.optional()
13731
+ }),
13732
+ value: strictObject({
13733
+ ...wait,
13734
+ autoContinue: waitAutoContinueDraftSchema.optional()
13735
+ })
13638
13736
  },
13639
13737
  "graph.node.webhook.set": {
13640
13738
  ...at,
@@ -13719,12 +13817,14 @@ function changeOperationsSchema(kind) {
13719
13817
  return toJSONSchema(schema, { io: "input" });
13720
13818
  }
13721
13819
  function checkModelVersion(content) {
13820
+ 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.");
13722
13821
  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.");
13723
13822
  if (content.modelVersion < 9 && Object.values(content.document.graph.nodes).some((candidateNode) => {
13724
13823
  if (candidateNode.onError != null) return true;
13725
13824
  if ([...Object.values("inputs" in candidateNode ? candidateNode.inputs : {}), ...Object.values(candidateNode.kind == "outputs" ? candidateNode.outputMappings : {})].some((candidateMapping) => candidateMapping.kind == "sources" && candidateMapping.sources.some((candidateSource) => candidateSource.kind == "node" && candidateSource.system))) return true;
13726
13825
  return candidateNode.kind == "condition" && candidateNode.cases.some((item) => item.groups.some((candidateGroup) => candidateGroup.expressions.some((expression) => [expression.left, expression.right].some((candidateOperand) => candidateOperand?.kind == "source" && candidateOperand.source.kind == "node" && candidateOperand.source.system))));
13727
13826
  })) throw new TypeError("Node error handling requires Flow model version 9.");
13827
+ if (content.modelVersion < 10 && Object.values(content.document.graph.nodes).some((candidate) => candidate.kind === "webhook-response")) throw new TypeError("Webhook response nodes require Flow model version 10.");
13728
13828
  if (content.modelVersion < 8 && Object.values(content.document.graph.nodes).some((candidateNode) => candidateNode.kind == "outputs")) throw new TypeError("Workflow outputs require Flow model version 8.");
13729
13829
  if (content.modelVersion < 7 && Object.values(content.document.graph.nodes).some((candidateNode) => candidateNode.kind == "start")) throw new TypeError("Start Triggers require Flow model version 7.");
13730
13830
  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.");
@@ -14303,6 +14403,7 @@ var patch = record$3(id$1, json$3);
14303
14403
  var authoringTypes = [
14304
14404
  "start",
14305
14405
  "outputs",
14406
+ "webhook-response",
14306
14407
  "workflow",
14307
14408
  "webhook",
14308
14409
  "cron",
@@ -14407,29 +14508,30 @@ var when = union([
14407
14508
  strictObject({ any: array(union([expression, all])) })
14408
14509
  ]);
14409
14510
  var authoringConfigurations = {
14410
- workflow: strictObject({ flowId: id$1 }),
14411
- start: strictObject({ inputDefs: flowInputFields.default({}) }),
14412
- outputs: strictObject({ outputDefs: flowOutputFields.default({}) }),
14413
- error: strictObject({ sourceFlowIds: array(id$1).optional() }),
14414
- webhook: authoringDefinitionSchemas.webhook.omit({ bodyFields: true }).extend({ body: inputFields }).strict(),
14415
- cron: strictObject({ schedule: authoringDefinitionSchemas.schedule }),
14416
- poll: strictObject({
14511
+ "webhook-response": strictObject({}),
14512
+ "workflow": strictObject({ flowId: id$1 }),
14513
+ "start": strictObject({ inputDefs: flowInputFields.default({}) }),
14514
+ "outputs": strictObject({ outputDefs: flowOutputFields.default({}) }),
14515
+ "error": strictObject({ sourceFlowIds: array(id$1).optional() }),
14516
+ "webhook": authoringDefinitionSchemas.webhook.omit({ bodyFields: true }).extend({ body: inputFields }).strict(),
14517
+ "cron": strictObject({ schedule: authoringDefinitionSchemas.schedule }),
14518
+ "poll": strictObject({
14417
14519
  key: id$1,
14418
14520
  connectionId: id$1.optional(),
14419
14521
  schedule: authoringDefinitionSchemas.schedule
14420
14522
  }),
14421
- integration: strictObject({
14523
+ "integration": strictObject({
14422
14524
  key: id$1,
14423
14525
  connectionId: id$1.optional()
14424
14526
  }),
14425
- code: strictObject({
14527
+ "code": strictObject({
14426
14528
  inputs: inputFields,
14427
14529
  outputs: outputFields,
14428
14530
  capabilities: authoringDefinitionSchemas.capabilities.optional()
14429
14531
  }),
14430
- connector: authoringDefinitionSchemas.connector.omit({ outputMode: true }).strict(),
14431
- openapi: authoringOpenApiSchema,
14432
- agent: authoringDefinitionSchemas.agent.omit({
14532
+ "connector": authoringDefinitionSchemas.connector.omit({ outputMode: true }).strict(),
14533
+ "openapi": authoringOpenApiSchema,
14534
+ "agent": authoringDefinitionSchemas.agent.omit({
14433
14535
  prompt: true,
14434
14536
  tools: true
14435
14537
  }).extend({
@@ -14438,9 +14540,9 @@ var authoringConfigurations = {
14438
14540
  tools: array(agentTool),
14439
14541
  notification: notification.optional()
14440
14542
  }).strict(),
14441
- llm: authoringLlmConfiguration.extend({ inputs: inputFields }),
14442
- decision: authoringDefinitionSchemas.decision,
14443
- condition: strictObject({
14543
+ "llm": authoringLlmConfiguration.extend({ inputs: inputFields }),
14544
+ "decision": authoringDefinitionSchemas.decision,
14545
+ "condition": strictObject({
14444
14546
  match: _enum(["first", "all"]),
14445
14547
  branches: array(strictObject({
14446
14548
  name: id$1,
@@ -14448,12 +14550,15 @@ var authoringConfigurations = {
14448
14550
  when
14449
14551
  }))
14450
14552
  }),
14451
- value: strictObject({
14553
+ "value": strictObject({
14452
14554
  values: patch,
14453
14555
  outputs: outputFields
14454
14556
  }),
14455
- wait: strictObject({ inputs: inputFields }),
14456
- approval: strictObject({ inputs: inputFields })
14557
+ "wait": strictObject({
14558
+ inputs: inputFields,
14559
+ autoContinue: authoringDefinitionSchemas.waitAutoContinue.optional().describe("Wait only. Omit to disable; clear config.autoContinue to remove. after counts from each wait registration; at requires an explicit offset and continues immediately if already past. Optional timezone preserves the editor zone; at remains the absolute instant. Server requires the deadline to precede the 7-day expiry.")
14560
+ }),
14561
+ "approval": strictObject({ inputs: inputFields })
14457
14562
  };
14458
14563
  var updates = strictObject({
14459
14564
  onError: _enum(["stop", "error"]).optional(),
@@ -14673,7 +14778,7 @@ function authoringSchema(kind) {
14673
14778
  "wait",
14674
14779
  "approval"
14675
14780
  ].includes(kind),
14676
- guidance: 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 == "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." : "Supply business configuration and input data. Fixed definitions are assembled by the tool. Existing constraints and defaults are preserved on partial updates.",
14781
+ 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." : "Supply business configuration and input data. Fixed definitions are assembled by the tool. Existing constraints and defaults are preserved on partial updates.",
14677
14782
  example: {
14678
14783
  op: "node.add",
14679
14784
  as: "step",
@@ -15017,6 +15122,7 @@ function triggerOutputPorts(trigger) {
15017
15122
  //#region src/flow/common/graph.ts
15018
15123
  function nodeInputPorts(node) {
15019
15124
  switch (node.kind) {
15125
+ case "webhook-response": return portsByHandle(webhookResponseInputs);
15020
15126
  case "outputs": return portsByHandle(node.outputDefs);
15021
15127
  case "condition": return conditionInputPorts(node);
15022
15128
  case "value": return {};
@@ -15063,7 +15169,8 @@ function resolutionOutputPorts(node) {
15063
15169
  pattern: "\\S"
15064
15170
  },
15065
15171
  ...Object.fromEntries(actions.map((action) => [`${action}Url`, { type: "string" }])),
15066
- expiresAt: { type: "string" }
15172
+ expiresAt: { type: "string" },
15173
+ ...node.kind == "wait" && node.autoContinue != null ? { autoContinueAt: { type: "string" } } : {}
15067
15174
  }),
15068
15175
  ...Object.fromEntries(actions.map((action) => [action, objectPort({
15069
15176
  inputs,
@@ -15075,6 +15182,7 @@ function resolutionOutputPorts(node) {
15075
15182
  }
15076
15183
  function nodeOutputPorts(node) {
15077
15184
  switch (node.kind) {
15185
+ case "webhook-response":
15078
15186
  case "outputs":
15079
15187
  case "condition": return {};
15080
15188
  case "value": return portsByHandle(node.values);
@@ -15455,18 +15563,52 @@ function createDecisionTask(identity, name = "AI Decision", questions) {
15455
15563
  function updateOutputsDefs(content, nodeId, value, outputMappings) {
15456
15564
  const node = content.document.graph.nodes[nodeId];
15457
15565
  if (node?.kind != "outputs") throw new TypeError("Expected an Outputs node.");
15458
- const mappings = outputMappings ?? remapInputMappings(node.outputMappings, value, renamedPort(node.outputDefs, value));
15566
+ const rename = renamedPort(node.outputDefs, value);
15567
+ const mappings = outputMappings ?? remapInputMappings(node.outputMappings, value, rename);
15459
15568
  const next = {
15460
15569
  ...node,
15461
15570
  outputDefs: value,
15462
15571
  outputMappings: mappings
15463
15572
  };
15464
- return dequal(node, next) ? [] : cleanVariableBindings(content, [{
15573
+ if (dequal(node, next)) return [];
15574
+ const changes = [{
15465
15575
  kind: "graph.node.replace",
15466
15576
  nodeId,
15467
15577
  before: node,
15468
15578
  node: next
15469
- }]);
15579
+ }];
15580
+ if (rename != null) for (const [id, trigger] of Object.entries(content.document.graph.nodes)) {
15581
+ if (trigger.kind != "webhook" || trigger.options == null) continue;
15582
+ const bodyRenamed = trigger.options.responseBody?.kind === "workflow-outputs" && trigger.options.responseBody.output === rename[0];
15583
+ const statusRenamed = trigger.options.responseStatusCodeOutput === rename[0];
15584
+ const headersRenamed = trigger.options.responseHeadersSource?.output === rename[0];
15585
+ const headerOutputs = trigger.options.responseHeaderOutputs;
15586
+ const headerRenamed = Object.values(headerOutputs ?? {}).includes(rename[0]);
15587
+ if (!bodyRenamed && !statusRenamed && !headersRenamed && !headerRenamed) continue;
15588
+ changes.push({
15589
+ kind: "graph.node.replace",
15590
+ nodeId: id,
15591
+ before: trigger,
15592
+ node: {
15593
+ ...trigger,
15594
+ options: {
15595
+ ...trigger.options,
15596
+ ...bodyRenamed ? { responseBody: {
15597
+ ...trigger.options.responseBody,
15598
+ kind: "workflow-outputs",
15599
+ output: rename[1]
15600
+ } } : {},
15601
+ ...statusRenamed ? { responseStatusCodeOutput: rename[1] } : {},
15602
+ ...headersRenamed ? { responseHeadersSource: {
15603
+ ...trigger.options.responseHeadersSource,
15604
+ output: rename[1]
15605
+ } } : {},
15606
+ ...headerRenamed ? { responseHeaderOutputs: Object.fromEntries(Object.entries(headerOutputs).map(([name, output]) => [name, output === rename[0] ? rename[1] : output])) } : {}
15607
+ }
15608
+ }
15609
+ });
15610
+ }
15611
+ return cleanVariableBindings(content, changes);
15470
15612
  }
15471
15613
  function renameFlowOutputSources(content, nodeIds, previous, next) {
15472
15614
  const rename = renamedPort(previous, next);
@@ -15767,7 +15909,7 @@ function authoringDiagnosticField(node, parts) {
15767
15909
  switch (node.kind) {
15768
15910
  case "condition": return head == "cases" || head == "matchMode" ? ["config", ...conditionConfigurationFieldPath(node, location)].join(".") : "config";
15769
15911
  case "wait":
15770
- case "approval": return head == "inputDefinitions" ? portField(node.inputDefinitions, location.slice(1), "config.inputs") : "config";
15912
+ case "approval": return head == "inputDefinitions" ? portField(node.inputDefinitions, location.slice(1), "config.inputs") : head == "autoContinue" ? ["config", ...location].join(".") : "config";
15771
15913
  case "start": return "config";
15772
15914
  case "webhook":
15773
15915
  if (head == "bodyFields") return portField(node.bodyFields, location.slice(1), "config.body");
@@ -16018,9 +16160,13 @@ function authoringNode(content, ref) {
16018
16160
  break;
16019
16161
  case "wait":
16020
16162
  case "approval":
16021
- config = { inputs: fieldsView(node.inputDefinitions) };
16163
+ config = {
16164
+ inputs: fieldsView(node.inputDefinitions),
16165
+ ...node.kind == "wait" && node.autoContinue != null ? { autoContinue: node.autoContinue } : {}
16166
+ };
16022
16167
  texts.prompt = node.prompt;
16023
16168
  break;
16169
+ case "webhook-response":
16024
16170
  case "manual":
16025
16171
  config = {};
16026
16172
  break;
@@ -16285,6 +16431,10 @@ async function compileAuthoring(base, request, host) {
16285
16431
  config: view.config
16286
16432
  }, patch));
16287
16433
  const explicit = (key) => Object.hasOwn(record(patch.config), key) || clear.some((path) => path[0] == "config" && path[1] == key);
16434
+ if (type == "wait") {
16435
+ const timing = record(record(patch.config).autoContinue);
16436
+ if (Object.hasOwn(timing, "kind") && timing.kind != record(record(view.config).autoContinue).kind) record(update.config).autoContinue = timing;
16437
+ }
16288
16438
  if (type == "openapi" && Object.hasOwn(record(patch.config), "authentication")) record(update.config).authentication = record(patch.config).authentication;
16289
16439
  for (const path of clear) clearPath(update, path);
16290
16440
  if (typeof update.name != "string") fail("node.name-required", "Node name cannot be cleared.");
@@ -16444,9 +16594,22 @@ async function compileAuthoring(base, request, host) {
16444
16594
  ...next,
16445
16595
  inputDefinitions: fieldsToPorts(config.inputs, node.inputDefinitions)
16446
16596
  };
16597
+ if (node.kind == "wait") {
16598
+ Reflect.deleteProperty(next, "autoContinue");
16599
+ if (config.autoContinue != null) Object.assign(next, { autoContinue: config.autoContinue });
16600
+ }
16447
16601
  break;
16448
16602
  case "webhook": {
16449
16603
  const { body, ...settings } = config;
16604
+ const responseOptions = record(settings.options);
16605
+ const responsePolicy = record(responseOptions.responseBody);
16606
+ if (responsePolicy.kind === "webhook-response" && typeof responsePolicy.nodeId === "string") settings.options = {
16607
+ ...responseOptions,
16608
+ responseBody: {
16609
+ ...responsePolicy,
16610
+ nodeId: resolve(responsePolicy.nodeId)
16611
+ }
16612
+ };
16450
16613
  const { options: _options, ...withoutOptions } = next;
16451
16614
  next = {
16452
16615
  ...withoutOptions,
@@ -16622,6 +16785,17 @@ async function compileAuthoring(base, request, host) {
16622
16785
  case "workflow":
16623
16786
  changes = createManagedTask(identity, await resolveWorkflow(String(authoringConfigurations.workflow.parse(config).flowId), name));
16624
16787
  break;
16788
+ case "webhook-response":
16789
+ changes = [{
16790
+ kind: "graph.node.create",
16791
+ nodeId,
16792
+ node: {
16793
+ kind: "webhook-response",
16794
+ name,
16795
+ inputs: {}
16796
+ }
16797
+ }];
16798
+ break;
16625
16799
  case "outputs":
16626
16800
  changes = [{
16627
16801
  kind: "graph.node.create",
@@ -16868,6 +17042,7 @@ var descriptions = {
16868
17042
  "start": "A Start node with a required message parameter. Supply it through trigger.outputs.",
16869
17043
  "error": "A Flow Error node. Select upstream Flows, then publish and enable this Flow to listen for failures in their automatic runs.",
16870
17044
  "webhook": "A Webhook start node.",
17045
+ "webhook-response": "An HTTP response node with body, statusCode and headers inputs. Select it from a reachable Webhook.",
16871
17046
  "cron": "An hourly scheduled start node.",
16872
17047
  "poll": "Gmail polling by key; replace CONNECTION_ID with an active Gmail connection.",
16873
17048
  "integration": "Telegram webhook integration by key; replace CONNECTION_ID with an active Telegram connection.",
@@ -16891,6 +17066,17 @@ var authoringExamples = Object.keys(descriptions).map((name) => ({
16891
17066
  function authoringExample(name) {
16892
17067
  let operations;
16893
17068
  switch (name) {
17069
+ case "webhook-response":
17070
+ operations = [{
17071
+ kind: "graph.node.create",
17072
+ nodeId: "reply",
17073
+ node: {
17074
+ kind: "webhook-response",
17075
+ name: "Webhook Response",
17076
+ inputs: {}
17077
+ }
17078
+ }];
17079
+ break;
16894
17080
  case "error":
16895
17081
  operations = createBuiltinTrigger("error", {
16896
17082
  kind: "error",
@@ -1923,7 +1923,7 @@ function timeSource(args) {
1923
1923
  function time(args) {
1924
1924
  return new RegExp(`^${timeSource(args)}$`);
1925
1925
  }
1926
- function datetime(args) {
1926
+ function datetime$1(args) {
1927
1927
  const opts = ["Z"];
1928
1928
  if (args.offset) opts.push(`([+-](?:[01]\\d|2[0-3]):[0-5]\\d)`);
1929
1929
  const qualified = `${timeSource({
@@ -2574,7 +2574,7 @@ var $ZodKSUID = /*@__PURE__*/ $constructor("$ZodKSUID", (inst, def) => {
2574
2574
  $ZodStringFormat.init(inst, def);
2575
2575
  });
2576
2576
  var $ZodISODateTime = /*@__PURE__*/ $constructor("$ZodISODateTime", (inst, def) => {
2577
- def.pattern ?? (def.pattern = datetime(def));
2577
+ def.pattern ?? (def.pattern = datetime$1(def));
2578
2578
  $ZodStringFormat.init(inst, def);
2579
2579
  });
2580
2580
  var $ZodISODate = /*@__PURE__*/ $constructor("$ZodISODate", (inst, def) => {
@@ -6571,6 +6571,11 @@ function preprocess(fn, schema) {
6571
6571
  });
6572
6572
  }
6573
6573
  //#endregion
6574
+ //#region ../../node_modules/.bun/zod@4.6.5/node_modules/zod/v4/classic/iso.js
6575
+ function datetime(params) {
6576
+ return /* @__PURE__ */ _isoDateTime(ZodISODateTime, params);
6577
+ }
6578
+ //#endregion
6574
6579
  //#region src/flow/common/retry.ts
6575
6580
  var nodeRetryLimits = {
6576
6581
  maxRetries: 5,
@@ -6600,6 +6605,32 @@ var triggerScheduleSchema = array(union([object({
6600
6605
  value: number()
6601
6606
  })]));
6602
6607
  //#endregion
6608
+ //#region src/localization/common/timeZone.ts
6609
+ /** Validate a named timezone using the same runtime data used for date conversion. */
6610
+ function isTimeZone(value) {
6611
+ try {
6612
+ Intl.DateTimeFormat("en", { timeZone: value });
6613
+ return true;
6614
+ } catch {
6615
+ return false;
6616
+ }
6617
+ }
6618
+ //#endregion
6619
+ //#region src/flow/common/wait.ts
6620
+ /** Drafts retain incomplete values; semantic validation gates publication and execution. */
6621
+ var waitAutoContinueDraftSchema = discriminatedUnion("kind", [strictObject({
6622
+ kind: literal("after"),
6623
+ durationMs: number().nullable()
6624
+ }), strictObject({
6625
+ kind: literal("at"),
6626
+ at: string(),
6627
+ timezone: string().optional()
6628
+ })]);
6629
+ discriminatedUnion("kind", [waitAutoContinueDraftSchema.options[0].extend({ durationMs: number().int().positive().max(Number.MAX_SAFE_INTEGER) }), waitAutoContinueDraftSchema.options[1].extend({
6630
+ at: datetime({ offset: true }),
6631
+ timezone: string().refine(isTimeZone, "Select a valid IANA timezone.").optional()
6632
+ })]);
6633
+ //#endregion
6603
6634
  //#region src/flow/common/webhookMethod.ts
6604
6635
  var webhookMethods = [
6605
6636
  "GET",
@@ -6608,6 +6639,24 @@ var webhookMethods = [
6608
6639
  "PATCH",
6609
6640
  "DELETE"
6610
6641
  ];
6642
+ //#endregion
6643
+ //#region src/flow/common/webhookResponse.ts
6644
+ var webhookResponseTimeout = {
6645
+ defaultMs: 3e4,
6646
+ minMs: 1e3,
6647
+ maxMs: 6e4
6648
+ };
6649
+ ({
6650
+ jsonSchema: {
6651
+ type: "object",
6652
+ additionalProperties: { type: [
6653
+ "string",
6654
+ "number",
6655
+ "boolean"
6656
+ ] }
6657
+ },
6658
+ nullable: true
6659
+ }).jsonSchema;
6611
6660
  var text = string();
6612
6661
  var actionConnection = text.describe("Account selection: omit while unconfigured; use an account ID to select it; use \"\" to explicitly defer configuration. Deferred Actions fail if called; deferred Agent tools are excluded from the callable tool set. Not supported by Triggers.");
6613
6662
  var json = json$1();
@@ -6835,9 +6884,24 @@ var webhookOptions = object({
6835
6884
  allowedMethods: never().optional(),
6836
6885
  allowedOrigins: strings.optional(),
6837
6886
  noResponseBody: never().optional(),
6887
+ responseBody: discriminatedUnion("kind", [strictObject({
6888
+ kind: literal("workflow-outputs"),
6889
+ output: text.optional(),
6890
+ timeoutMs: number().int().min(webhookResponseTimeout.minMs).max(webhookResponseTimeout.maxMs).optional()
6891
+ }), strictObject({
6892
+ kind: literal("webhook-response"),
6893
+ nodeId: text.optional(),
6894
+ timeoutMs: number().int().min(webhookResponseTimeout.minMs).max(webhookResponseTimeout.maxMs).optional()
6895
+ })]).optional(),
6838
6896
  responseData: text.optional(),
6839
6897
  responseHeaders: record$1(text, text).optional(),
6840
- responseStatusCode: number().int().min(200).max(599).optional()
6898
+ responseHeadersSource: strictObject({
6899
+ kind: literal("workflow-outputs"),
6900
+ output: text.optional()
6901
+ }).optional(),
6902
+ responseHeaderOutputs: record$1(text, text).optional(),
6903
+ responseStatusCode: number().int().min(200).max(599).optional(),
6904
+ responseStatusCodeOutput: text.optional()
6841
6905
  });
6842
6906
  var webhook = {
6843
6907
  bodyFields: array(input),
@@ -6892,6 +6956,12 @@ var base = {
6892
6956
  onError: _enum(["stop", "error"]).optional()
6893
6957
  };
6894
6958
  var node = union([
6959
+ strictObject({
6960
+ ...base,
6961
+ kind: literal("webhook-response"),
6962
+ retry: never().optional(),
6963
+ onError: never().optional()
6964
+ }),
6895
6965
  strictObject({
6896
6966
  ...base,
6897
6967
  kind: literal("outputs"),
@@ -6924,7 +6994,8 @@ var node = union([
6924
6994
  strictObject({
6925
6995
  ...base,
6926
6996
  kind: literal("wait"),
6927
- ...wait
6997
+ ...wait,
6998
+ autoContinue: waitAutoContinueDraftSchema.optional()
6928
6999
  }).omit({ timeoutMs: true }),
6929
7000
  object({
6930
7001
  ...trigger,
@@ -7011,7 +7082,8 @@ object({
7011
7082
  literal(6),
7012
7083
  literal(7),
7013
7084
  literal(8),
7014
- literal(9)
7085
+ literal(9),
7086
+ literal(10)
7015
7087
  ]),
7016
7088
  document,
7017
7089
  modules: record$1(text, module)
@@ -7136,8 +7208,14 @@ var shapes = {
7136
7208
  },
7137
7209
  "graph.node.resolution.set": {
7138
7210
  ...at,
7139
- before: object(wait),
7140
- value: object(wait)
7211
+ before: strictObject({
7212
+ ...wait,
7213
+ autoContinue: waitAutoContinueDraftSchema.optional()
7214
+ }),
7215
+ value: strictObject({
7216
+ ...wait,
7217
+ autoContinue: waitAutoContinueDraftSchema.optional()
7218
+ })
7141
7219
  },
7142
7220
  "graph.node.webhook.set": {
7143
7221
  ...at,
@@ -3,7 +3,9 @@ export interface EngineContract {
3
3
  readonly platformExports: ReadonlySet<string>;
4
4
  readonly platformModule: string;
5
5
  readonly platformSource: string;
6
+ readonly waitAutoContinue?: boolean;
7
+ readonly webhookResponses?: boolean;
6
8
  }
7
- export declare const currentEngineContract = "open-flow-engine/v6";
8
- export declare const nodejsEngineContract = "open-flow-engine/v6/nodejs-compat-v1";
9
+ export declare const currentEngineContract = "open-flow-engine/v7";
10
+ export declare const nodejsEngineContract = "open-flow-engine/v7/nodejs-compat-v1";
9
11
  export declare function findEngineContract(contract: string): EngineContract | undefined;