@oomol-lab/open-flow 0.1.0-beta.64 → 0.1.0-beta.66

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 (50) hide show
  1. package/dist/browser/{createResourceDialog-BAJXbzNH.js → createResourceDialog-C-Si_cYs.js} +2 -2
  2. package/dist/browser/flow-authoring-node.d.ts +12 -3
  3. package/dist/browser/flow-authoring.js +135 -21
  4. package/dist/browser/flow-change-schema.d.ts +3 -1
  5. package/dist/browser/flow-change.d.ts +15 -3
  6. package/dist/browser/flow-change.js +111 -16
  7. package/dist/browser/{flowChanges-BAMkSaKF.js → flowChanges-T4_R5p1f.js} +3031 -2124
  8. package/dist/browser/{flowRunInputEditorStore-B2Rw4VsT.js → flowRunInputEditorStore-DJqmR6Qh.js} +3 -2
  9. package/dist/browser/{flowWorkspace-DxLc1Ybv.js → flowWorkspace-C0J5C0oM.js} +754 -163
  10. package/dist/browser/{icons-Db2Jb2iX.js → icons-BD3m0RQq.js} +4484 -4370
  11. package/dist/browser/preview.css +160 -64
  12. package/dist/browser/preview.js +6487 -5232
  13. package/dist/browser/ui.css +93 -3
  14. package/dist/browser/ui.js +8 -5
  15. package/dist/browser/workbench.css +160 -64
  16. package/dist/browser/workbench.js +175 -59
  17. package/dist/browser/{workbenchSelect-C-jf6NIM.js → workbenchSelect-B-PFpF_Q.js} +1 -1
  18. package/dist/command/index.js +49 -49
  19. package/dist/common/authoring.d.ts +7 -5
  20. package/dist/common/authoringExamples.d.ts +3 -3
  21. package/dist/common/authoringFields.d.ts +20 -0
  22. package/dist/common/authoringSchema.d.ts +404 -15
  23. package/dist/common/connectorDecoders.d.ts +2 -1
  24. package/dist/common/control-api-conformance.js +403 -137
  25. package/dist/common/control-api.d.ts +70 -7
  26. package/dist/common/control-api.js +3587 -3428
  27. package/dist/common/control-requests.d.ts +10 -3
  28. package/dist/common/control-requests.js +463 -48
  29. package/dist/common/decision.js +28 -3
  30. package/dist/common/flow-encoding.d.ts +4 -2
  31. package/dist/common/flow-encoding.js +144 -10
  32. package/dist/common/flow-graph.d.ts +1 -1
  33. package/dist/common/flow-semantics.d.ts +12 -2
  34. package/dist/common/flow-semantics.js +152 -33
  35. package/dist/common/integration-trigger.js +28 -3
  36. package/dist/common/liveDetails.d.ts +26 -11
  37. package/dist/common/mcp.d.ts +6 -3
  38. package/dist/common/mcp.js +3541 -3403
  39. package/dist/common/openapi.js +28 -3
  40. package/dist/common/poll-trigger.js +28 -3
  41. package/dist/common/run-events.d.ts +2 -0
  42. package/dist/common/run-events.js +9 -3
  43. package/dist/common/scheduler.d.ts +11 -1
  44. package/dist/common/scheduler.js +216 -48
  45. package/dist/common/trigger-contract.d.ts +2 -0
  46. package/dist/common/webhook-trigger.js +28 -3
  47. package/dist/common/workflow.d.ts +93 -0
  48. package/dist/common/workflow.js +10491 -0
  49. package/package.json +5 -1
  50. package/skills/open-flow/references/flow-authoring.md +26 -16
@@ -6810,6 +6810,7 @@ function conditionOperands(node) {
6810
6810
  }] : []])));
6811
6811
  }
6812
6812
  function nodeInputMappings(node) {
6813
+ if (node.kind == "outputs") return node.outputMappings;
6813
6814
  if (node.kind != "condition") return "inputs" in node ? node.inputs : {};
6814
6815
  return Object.fromEntries(conditionOperands(node).flatMap(({ handle, operand }) => operand.kind == "source" ? [[handle, {
6815
6816
  kind: "sources",
@@ -6978,6 +6979,45 @@ function decodeConnectorCapabilities(value) {
6978
6979
  };
6979
6980
  });
6980
6981
  }
6982
+ function isTriggerNode(node) {
6983
+ return [
6984
+ "manual",
6985
+ "start",
6986
+ "error",
6987
+ "webhook",
6988
+ "cron",
6989
+ "poll",
6990
+ "integration"
6991
+ ].includes(node.kind);
6992
+ }
6993
+ /** Lossless upgrade of readable content. Historical content and its encoding stay unchanged. */
6994
+ function upgradeRevisionContent(content) {
6995
+ const upgraded = upgradeDecodedRevisionContent(decodeRevisionContent(content));
6996
+ return dequal(content, upgraded) ? content : upgraded;
6997
+ }
6998
+ function upgradeDecodedRevisionContent(content) {
6999
+ const graph = content.document.graph;
7000
+ const hasManual = Object.values(graph.nodes).some((node) => node.kind == "manual");
7001
+ if (!hasManual && content.modelVersion == 8) return content;
7002
+ return {
7003
+ ...content,
7004
+ modelVersion: 8,
7005
+ document: {
7006
+ ...content.document,
7007
+ graph: hasManual ? {
7008
+ ...graph,
7009
+ nodes: Object.fromEntries(Object.entries(graph.nodes).map(([id, node]) => [id, upgradeManualTrigger(node)]))
7010
+ } : graph
7011
+ }
7012
+ };
7013
+ }
7014
+ function upgradeManualTrigger(node) {
7015
+ return node.kind == "manual" ? {
7016
+ ...node,
7017
+ kind: "start",
7018
+ inputDefs: []
7019
+ } : node;
7020
+ }
6981
7021
  function normalizeNodeName(value) {
6982
7022
  return value.trim().normalize("NFC");
6983
7023
  }
@@ -6996,8 +7036,9 @@ function invalid(message) {
6996
7036
  throw new FlowChangeError(message);
6997
7037
  }
6998
7038
  function applyFlowChanges(content, operations) {
6999
- const document = { ...content.document };
7000
- const modules = { ...content.modules };
7039
+ const source = content.modelVersion != 8 || Object.values(content.document.graph.nodes).some((node) => node.kind == "manual") ? decodeRevisionContent(content) : content;
7040
+ const document = { ...source.document };
7041
+ const modules = { ...source.modules };
7001
7042
  for (const operation of operations) switch (operation.kind) {
7002
7043
  case "graph.trigger.sources.set": {
7003
7044
  const graph = document.graph;
@@ -7048,8 +7089,9 @@ function applyFlowChanges(content, operations) {
7048
7089
  case "graph.edge.connect": {
7049
7090
  const graph = document.graph;
7050
7091
  if (graph.nodes[operation.edge.source] == null) invalid("The source Node does not exist.");
7092
+ if (graph.nodes[operation.edge.source]?.kind == "outputs") invalid("Outputs cannot have downstream execution edges.");
7051
7093
  const node = graph.nodes[operation.edge.target];
7052
- if (node == null || !("inputs" in node)) invalid("The target Node does not accept execution dependencies.");
7094
+ if (node == null || isTriggerNode(node)) invalid("The target Node does not accept execution dependencies.");
7053
7095
  if (graph.edges.some((edge) => dequal(edge, operation.edge))) invalid("The Nodes are already connected.");
7054
7096
  Object.assign(document, { graph: {
7055
7097
  ...graph,
@@ -7129,9 +7171,10 @@ function applyFlowChanges(content, operations) {
7129
7171
  const graph = document.graph;
7130
7172
  if (graph.nodes[operation.nodeId] != null) invalid("A Node with this ID already exists in the target graph.");
7131
7173
  if (operation.node.kind == "error" && Object.values(graph.nodes).some((node) => node.kind == "error")) invalid("A graph can contain only one Flow Error node.");
7132
- if (operation.node.kind == "manual" && Object.values(graph.nodes).some((node) => node.kind == "manual")) invalid("A graph can contain only one manual Trigger.");
7174
+ if ((operation.node.kind == "manual" || operation.node.kind == "start") && Object.values(graph.nodes).some((node) => node.kind == "manual" || node.kind == "start")) invalid("A graph can contain only one Start Trigger.");
7133
7175
  if (operation.node.kind == "task" && "moduleId" in operation.node.task && operation.node.task.capabilities !== void 0) decodeConnectorCapabilities(operation.node.task.capabilities);
7134
7176
  if (operation.node.name == null) invalid("A Node name cannot be empty.");
7177
+ if (operation.node.kind == "outputs" && Object.values(graph.nodes).some((node) => node.kind == "outputs")) invalid("A graph can contain only one Outputs node.");
7135
7178
  const name = normalizeNodeName(operation.node.name);
7136
7179
  const issue = nodeNameIssue(graph, operation.nodeId, name);
7137
7180
  if (issue == "empty") invalid("A Node name cannot be empty.");
@@ -7189,11 +7232,24 @@ function applyFlowChanges(content, operations) {
7189
7232
  case "graph.node.input.set": {
7190
7233
  const graph = document.graph;
7191
7234
  const node = graph.nodes[operation.nodeId];
7192
- if (node == null || !("inputs" in node)) invalid("The Node does not accept inputs.");
7235
+ if (node == null || isTriggerNode(node)) invalid("The Node does not accept inputs.");
7193
7236
  if (!dequal(nodeInputMappings(node)[operation.handle], operation.before)) invalid("The Node input changed before this operation was applied.");
7194
- const inputs = { ...node.inputs };
7237
+ const inputs = { ...nodeInputMappings(node) };
7195
7238
  if (operation.value == null) delete inputs[operation.handle];
7196
7239
  else inputs[operation.handle] = operation.value;
7240
+ if (node.kind == "outputs") {
7241
+ document.graph = {
7242
+ ...graph,
7243
+ nodes: {
7244
+ ...graph.nodes,
7245
+ [operation.nodeId]: {
7246
+ ...node,
7247
+ outputMappings: inputs
7248
+ }
7249
+ }
7250
+ };
7251
+ break;
7252
+ }
7197
7253
  Object.assign(document, { graph: {
7198
7254
  ...graph,
7199
7255
  nodes: {
@@ -7421,11 +7477,11 @@ function applyFlowChanges(content, operations) {
7421
7477
  }
7422
7478
  }
7423
7479
  assertOpenApiAuthBindings(document);
7424
- return {
7480
+ return upgradeDecodedRevisionContent({
7425
7481
  document,
7426
- modelVersion: 6,
7482
+ modelVersion: 8,
7427
7483
  modules
7428
- };
7484
+ });
7429
7485
  }
7430
7486
  //#endregion
7431
7487
  //#region src/json-schema-subset/utils.ts
@@ -10375,6 +10431,7 @@ var port = object$1({
10375
10431
  nullable: boolean(),
10376
10432
  handle: text$1
10377
10433
  });
10434
+ var workflowInputDefs = array(port.strict());
10378
10435
  var input = port.extend({ value: json$4.optional() });
10379
10436
  var group = object$1({
10380
10437
  collapsed: boolean().optional(),
@@ -10532,6 +10589,11 @@ var managedFields = object$1({
10532
10589
  messageHandle: text$1,
10533
10590
  inputs: record$3(text$1, agentValue)
10534
10591
  }).optional()
10592
+ }),
10593
+ strictObject({
10594
+ kind: literal("workflow"),
10595
+ flowId: text$1,
10596
+ revisionId: text$1
10535
10597
  })
10536
10598
  ])
10537
10599
  });
@@ -10640,6 +10702,12 @@ var base = {
10640
10702
  timeoutMs: number().optional()
10641
10703
  };
10642
10704
  var node = union([
10705
+ strictObject({
10706
+ ...base,
10707
+ kind: literal("outputs"),
10708
+ outputDefs: array(port.strict()),
10709
+ outputMappings: inputs$1
10710
+ }).omit({ inputs: true }),
10643
10711
  object$1({
10644
10712
  ...base,
10645
10713
  inputs: record$3(text$1, never()),
@@ -10672,6 +10740,11 @@ var node = union([
10672
10740
  ...trigger$1,
10673
10741
  kind: literal("manual")
10674
10742
  }),
10743
+ strictObject({
10744
+ ...trigger$1,
10745
+ kind: literal("start"),
10746
+ inputDefs: workflowInputDefs
10747
+ }),
10675
10748
  strictObject({
10676
10749
  ...trigger$1,
10677
10750
  kind: literal("error"),
@@ -10751,35 +10824,51 @@ var module = object$1({
10751
10824
  imports: strings,
10752
10825
  source: text$1
10753
10826
  });
10754
- var document = preprocess(rejectRetiredDefinitions, object$1({
10827
+ var document = preprocess(normalizeDocument, object$1({
10755
10828
  bindings: record$3(text$1, binding),
10756
10829
  graph
10757
10830
  }));
10758
- object$1({
10831
+ var revision = object$1({
10759
10832
  modelVersion: union([
10760
10833
  literal(2),
10761
10834
  literal(4),
10762
10835
  literal(5),
10763
- literal(6)
10836
+ literal(6),
10837
+ literal(7),
10838
+ literal(8)
10764
10839
  ]),
10765
10840
  document,
10766
10841
  modules: record$3(text$1, module)
10767
- }).extend({
10842
+ });
10843
+ revision.extend({
10768
10844
  kind: literal("open-flow-flow-revision"),
10769
10845
  version: literal(1)
10770
10846
  });
10771
- function rejectRetiredDefinitions(value) {
10847
+ function normalizeDocument(value) {
10772
10848
  const candidate = record$2(value);
10773
10849
  if (candidate.tasks !== void 0 && (candidate.tasks === null || typeof candidate.tasks !== "object" || Array.isArray(candidate.tasks) || Object.keys(candidate.tasks).length > 0)) throw new TypeError("Independent Task definitions are no longer supported.");
10774
10850
  if (Object.values(record$2(record$2(candidate.graph).nodes)).some((candidateNode) => Object.hasOwn(record$2(candidateNode), "taskId"))) throw new TypeError("Task references are no longer supported.");
10775
10851
  const subflows = candidate.subflows;
10776
10852
  if (subflows !== void 0 && (subflows === null || typeof subflows !== "object" || Array.isArray(subflows) || Object.keys(subflows).length > 0)) throw new TypeError("Subflows are no longer supported.");
10777
10853
  if (Object.values(record$2(record$2(candidate.graph).nodes)).some((candidateNode) => record$2(candidateNode).kind === "subflow")) throw new TypeError("Subflow nodes are no longer supported.");
10854
+ if ([
10855
+ "inputDefs",
10856
+ "outputDefs",
10857
+ "outputMappings"
10858
+ ].some((field) => Object.hasOwn(candidate, field))) throw new TypeError("Workflow interface configuration must belong to Start and Outputs nodes.");
10859
+ if (Object.values(record$2(record$2(candidate.graph).nodes)).some((candidateNode) => record$2(candidateNode).kind == "start" && Object.hasOwn(record$2(candidateNode), "parameters"))) throw new TypeError("Legacy Start.parameters is unsupported; configure node.inputDefs.");
10778
10860
  return value;
10779
10861
  }
10780
10862
  function record$2(value) {
10781
10863
  return value != null && typeof value == "object" && !Array.isArray(value) ? value : {};
10782
10864
  }
10865
+ function decodeRevisionContent(value) {
10866
+ checkJsonDepth(value);
10867
+ const content = revision.parse(value);
10868
+ checkModelVersion(content);
10869
+ assertOpenApiAuthBindings(content.document);
10870
+ return content;
10871
+ }
10783
10872
  var shapes = {
10784
10873
  "graph.trigger.sources.set": {
10785
10874
  nodeId: text$1,
@@ -10956,6 +11045,12 @@ function changeOperationsSchema(kind) {
10956
11045
  if (schema == null) throw new TypeError(`Unknown operation ${JSON.stringify(kind)}.`);
10957
11046
  return toJSONSchema(schema, { io: "input" });
10958
11047
  }
11048
+ function checkModelVersion(content) {
11049
+ 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.");
11050
+ 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.");
11051
+ 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.");
11052
+ 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.");
11053
+ }
10959
11054
  //#endregion
10960
11055
  //#region src/control/common/authoringLlm.ts
10961
11056
  var authoringLlmConfiguration = strictObject({
@@ -11527,7 +11622,9 @@ var id$2 = string().min(1);
11527
11622
  var json$3 = json$5();
11528
11623
  var patch = record$3(id$2, json$3);
11529
11624
  var authoringTypes = [
11530
- "manual",
11625
+ "start",
11626
+ "outputs",
11627
+ "workflow",
11531
11628
  "webhook",
11532
11629
  "cron",
11533
11630
  "error",
@@ -11600,6 +11697,12 @@ var field = strictObject({
11600
11697
  description: string().optional()
11601
11698
  });
11602
11699
  var inputFields = record$3(id$2, field.extend({ default: json$3.optional() })).describe("Optional business input constraints by name. A binding to a new Code, Agent, LLM, Wait or Approval input automatically declares an input accepting any JSON. Existing constraints are preserved. Omitted schema accepts any JSON; omitted nullable is true. Use default for inherited values; input.set supplies data.");
11700
+ var flowInputFields = record$3(id$2, field).describe("Workflow input definitions by name. Omitted schema accepts any JSON; omitted nullable is true. No defaults. Supply call values as trigger.outputs.");
11701
+ var flowOutputFields = flowInputFields.describe("Workflow output definitions by name. Omitted schema accepts any JSON; omitted nullable is true. No defaults. Set values on the Outputs node with input.set or node.add.inputs.");
11702
+ var flowInputFieldsView = record$3(id$2, field.extend({
11703
+ schema: json$3,
11704
+ nullable: boolean()
11705
+ }));
11603
11706
  var outputFields = record$3(id$2, field).describe("Code return fields by name. Omitted schema accepts any JSON; omitted nullable is true.");
11604
11707
  var expression = strictObject({
11605
11708
  left: operand,
@@ -11613,7 +11716,9 @@ var when = union([
11613
11716
  strictObject({ any: array(union([expression, all])) })
11614
11717
  ]);
11615
11718
  var authoringConfigurations = {
11616
- manual: strictObject({}),
11719
+ workflow: strictObject({ flowId: id$2 }),
11720
+ start: strictObject({ inputDefs: flowInputFields.default({}) }),
11721
+ outputs: strictObject({ outputDefs: flowOutputFields.default({}) }),
11617
11722
  error: strictObject({ sourceFlowIds: array(id$2).optional() }),
11618
11723
  webhook: authoringDefinitionSchemas.webhook.omit({ bodyFields: true }).extend({ body: inputFields }).strict(),
11619
11724
  cron: strictObject({ schedule: authoringDefinitionSchemas.schedule }),
@@ -11684,6 +11789,10 @@ var authoringEditSchema = discriminatedUnion("op", [
11684
11789
  set: updates.optional(),
11685
11790
  clear: array(array(id$2).min(1)).optional()
11686
11791
  }),
11792
+ strictObject({
11793
+ op: literal("node.refresh"),
11794
+ node: referenceSchema
11795
+ }),
11687
11796
  strictObject({
11688
11797
  op: literal("node.remove"),
11689
11798
  node: referenceSchema
@@ -11747,7 +11856,7 @@ var authoringSchemaQuery = strictObject({
11747
11856
  var requestContracts = {
11748
11857
  read: {
11749
11858
  schema: authoringReadSchema,
11750
- guidance: "Choose one mode: outline (omit nodes and text), node details (nodes), or text excerpt (text). nodes and text are mutually exclusive. Text defaults to 80 lines, at most 200 lines and 24000 characters. For the complete text, repeat at nextStart with the same revision until truncated is false.",
11859
+ guidance: "Read Start and Outputs node details for their interface definitions and data sources. Choose one mode: outline (omit nodes and text), node details (nodes), or text excerpt (text). nodes and text are mutually exclusive. Text defaults to 80 lines, at most 200 lines and 24000 characters. For the complete text, repeat at nextStart with the same revision until truncated is false.",
11751
11860
  examples: [
11752
11861
  {},
11753
11862
  {
@@ -11775,7 +11884,7 @@ var requestContracts = {
11775
11884
  },
11776
11885
  edit: {
11777
11886
  schema: authoringRequestSchema,
11778
- guidance: "Use the observed revision as baseRevision and a stable requestId. Edits are ordered and atomic. node.add.as declares a batch-local alias without $. Every later reference to that new node must use $alias, including node, edge source/target and output source node fields; a bare alias is not the node ID. Use returned node references in later batches. Updates recursively merge objects (including schemas); {} preserves existing fields. Arrays replace as a whole. Remove fields with clear paths. Text replacement requires exactly one match. Read the target text first. A saved draft can have validation diagnostics.",
11887
+ guidance: "Edit Start config.inputDefs and Outputs config.outputDefs through node.add or node.update; clear paths are relative to the node, e.g. [\"config\",\"inputDefs\",\"amount\"]. Set Outputs values with input.set. Use the observed revision as baseRevision and a stable requestId. Edits are ordered and atomic. node.add.as declares a batch-local alias without $. Every later reference to that new node must use $alias, including node, edge source/target and output source node fields; a bare alias is not the node ID. Use returned node references in later batches. Updates recursively merge objects (including schemas); {} preserves existing fields. Arrays replace as a whole. Remove fields with clear paths. Text replacement requires exactly one match. Read the target text first. A saved draft can have validation diagnostics.",
11779
11888
  examples: [{
11780
11889
  baseRevision: "REVISION",
11781
11890
  requestId: "CREATE_REQUEST",
@@ -11783,7 +11892,7 @@ var requestContracts = {
11783
11892
  {
11784
11893
  op: "node.add",
11785
11894
  as: "start",
11786
- type: "manual",
11895
+ type: "start",
11787
11896
  name: "Start"
11788
11897
  },
11789
11898
  {
@@ -11844,7 +11953,8 @@ function authoringSchema(kind) {
11844
11953
  "unset",
11845
11954
  "default"
11846
11955
  ] : [
11847
- "manual",
11956
+ "start",
11957
+ "outputs",
11848
11958
  "error",
11849
11959
  "cron",
11850
11960
  "webhook",
@@ -11865,13 +11975,16 @@ function authoringSchema(kind) {
11865
11975
  "wait",
11866
11976
  "approval"
11867
11977
  ].includes(kind),
11868
- guidance: kind == "condition" ? "Edit branch operands through config.branches. A branch can test one expression, all expressions, or any alternatives. Unmatched execution uses branch otherwise." : ["poll", "integration"].includes(kind) ? "Configure static parameters with node.add.inputs or input.set. Definitions come from the selected Trigger key; execution output and variable sources are unavailable." : kind == "llm" ? "Configure model settings, message templates and history as defaults. Input bindings with the same names override these defaults; named business inputs can be bound directly. Template strings interpolate {{name}}." : kind == "openapi" ? "Select an operation; the tool resolves its ports and authentication. Read authenticationChoices from node details. authentication is replaced as a complete choice. Bind advertised credentials through inputs." : "Supply business configuration and input data. Fixed definitions are assembled by the tool. Existing constraints and defaults are preserved on partial updates.",
11978
+ 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.",
11869
11979
  example: {
11870
11980
  op: "node.add",
11871
11981
  as: "step",
11872
11982
  type: kind,
11873
11983
  name: "Step",
11874
11984
  ...{
11985
+ start: { config: { inputDefs: {} } },
11986
+ outputs: { config: { outputDefs: {} } },
11987
+ workflow: { config: { flowId: "<Flow ID>" } },
11875
11988
  connector: { config: {
11876
11989
  action: "<Action ID>",
11877
11990
  connectionId: "<Connection ID>"
@@ -12026,7 +12139,7 @@ var authoringSearchResponse = object$1({
12026
12139
  revision: id$2,
12027
12140
  data: object$1({
12028
12141
  matches: array(object$1({
12029
- node: id$2,
12142
+ node: id$2.optional(),
12030
12143
  field: id$2,
12031
12144
  line: int().optional(),
12032
12145
  excerpt: string()
@@ -12044,6 +12157,41 @@ function connectorOutputMode(schema) {
12044
12157
  return properties != null && Object.keys(properties).length > 0 || root?.type == "object" && root.additionalProperties === false ? "fields" : "value";
12045
12158
  }
12046
12159
  //#endregion
12160
+ //#region src/flow/common/edgeChanges.ts
12161
+ function connect(content, edge) {
12162
+ const selected = content.document.graph;
12163
+ if (selected?.edges.some((candidate) => dequal(candidate, edge))) return [];
12164
+ const changes = [{
12165
+ edge,
12166
+ kind: "graph.edge.connect"
12167
+ }];
12168
+ const source = selected.nodes[edge.source];
12169
+ const target = selected.nodes[edge.target];
12170
+ if (edge.sourceHandle == "pending" && (source?.kind == "approval" || source?.kind == "wait") && target?.kind == "task" && "executor" in target.task && target.task.executor.kind == "connector" && target.task.executor.action == "leina.send_notification" && (target.inputs.message == null || target.inputs.message.kind == "unset")) changes.push({
12171
+ kind: "graph.node.input.set",
12172
+ nodeId: edge.target,
12173
+ handle: "message",
12174
+ before: target.inputs.message,
12175
+ value: {
12176
+ kind: "sources",
12177
+ sources: [{
12178
+ kind: "node",
12179
+ nodeId: edge.source,
12180
+ output: "pending",
12181
+ field: "message"
12182
+ }]
12183
+ }
12184
+ });
12185
+ return changes;
12186
+ }
12187
+ function disconnect(content, edge) {
12188
+ if (!content.document.graph?.edges.some((candidate) => dequal(candidate, edge))) return [];
12189
+ return [{
12190
+ edge,
12191
+ kind: "graph.edge.disconnect"
12192
+ }];
12193
+ }
12194
+ //#endregion
12047
12195
  //#region src/trigger/common/contract.ts
12048
12196
  var errorOutputs = [
12049
12197
  {
@@ -12152,6 +12300,7 @@ function triggerOutputDefinitions(trigger) {
12152
12300
  switch (trigger.kind) {
12153
12301
  case "error": return errorOutputs;
12154
12302
  case "manual": return [];
12303
+ case "start": return trigger.inputDefs;
12155
12304
  case "cron": return cronOutputs;
12156
12305
  case "poll":
12157
12306
  case "integration": return trigger.definition.outputs;
@@ -12170,6 +12319,7 @@ function triggerOutputPorts(trigger) {
12170
12319
  //#region src/flow/common/graph.ts
12171
12320
  function nodeInputPorts(node) {
12172
12321
  switch (node.kind) {
12322
+ case "outputs": return portsByHandle(node.outputDefs);
12173
12323
  case "condition": return conditionInputPorts(node);
12174
12324
  case "value": return {};
12175
12325
  case "task": return portsByHandle([...node.task.inputs, ...node.additionalInputs ?? []]);
@@ -12180,6 +12330,7 @@ function nodeInputPorts(node) {
12180
12330
  case "poll":
12181
12331
  case "error":
12182
12332
  case "manual":
12333
+ case "start":
12183
12334
  case "webhook": return {};
12184
12335
  }
12185
12336
  }
@@ -12207,6 +12358,12 @@ function resolutionOutputPorts(node) {
12207
12358
  pending: objectPort({
12208
12359
  inputs,
12209
12360
  prompt: { type: "string" },
12361
+ pageUrl: { type: "string" },
12362
+ message: {
12363
+ type: "string",
12364
+ minLength: 1,
12365
+ pattern: "\\S"
12366
+ },
12210
12367
  ...Object.fromEntries(actions.map((action) => [`${action}Url`, { type: "string" }])),
12211
12368
  expiresAt: { type: "string" }
12212
12369
  }),
@@ -12220,6 +12377,7 @@ function resolutionOutputPorts(node) {
12220
12377
  }
12221
12378
  function nodeOutputPorts(node) {
12222
12379
  switch (node.kind) {
12380
+ case "outputs":
12223
12381
  case "condition": return {};
12224
12382
  case "value": return portsByHandle(node.values);
12225
12383
  case "task": return portsByHandle(node.task.outputs);
@@ -12230,6 +12388,7 @@ function nodeOutputPorts(node) {
12230
12388
  case "poll":
12231
12389
  case "error":
12232
12390
  case "manual":
12391
+ case "start":
12233
12392
  case "webhook": return triggerOutputPorts(node);
12234
12393
  }
12235
12394
  }
@@ -12254,6 +12413,42 @@ async function imports(source) {
12254
12413
  }
12255
12414
  }
12256
12415
  //#endregion
12416
+ //#region src/flow/common/portChanges.ts
12417
+ function renamedPort(previous, next) {
12418
+ const previousNames = new Set(previous.flatMap((port) => "handle" in port ? [port.handle] : []));
12419
+ const nextNames = new Set(next.flatMap((port) => "handle" in port ? [port.handle] : []));
12420
+ const removed = [...previousNames].filter((name) => !nextNames.has(name));
12421
+ const added = [...nextNames].filter((name) => !previousNames.has(name));
12422
+ return removed.length == 1 && added.length == 1 ? [removed[0], added[0]] : void 0;
12423
+ }
12424
+ function renameOutputMapping(mapping, nodeIds, rename) {
12425
+ if (rename == null || mapping.kind != "sources") return mapping;
12426
+ const sources = mapping.sources.map((source) => source.kind == "node" && nodeIds.has(source.nodeId) && source.output == rename[0] ? {
12427
+ ...source,
12428
+ output: rename[1]
12429
+ } : source);
12430
+ return sources.every((source, index) => source === mapping.sources[index]) ? mapping : {
12431
+ kind: "sources",
12432
+ sources
12433
+ };
12434
+ }
12435
+ /** Carry saved mappings through a field rename and remove only fields absent from the new contract. */
12436
+ function remapInputMappings(mappings, ports, rename) {
12437
+ const inputs = { ...mappings };
12438
+ if (rename != null && Object.hasOwn(inputs, rename[0])) {
12439
+ Object.defineProperty(inputs, rename[1], {
12440
+ value: inputs[rename[0]],
12441
+ enumerable: true,
12442
+ configurable: true,
12443
+ writable: true
12444
+ });
12445
+ delete inputs[rename[0]];
12446
+ }
12447
+ const names = new Set(ports.flatMap((port) => "handle" in port ? [port.handle] : []));
12448
+ for (const name of Object.keys(inputs)) if (!names.has(name)) delete inputs[name];
12449
+ return inputs;
12450
+ }
12451
+ //#endregion
12257
12452
  //#region src/flow/common/nodeChanges.ts
12258
12453
  var codeTaskTemplate = `export default async function (inputs, context) {
12259
12454
  return { result: inputs.value }
@@ -12503,7 +12698,7 @@ function bindingReferences(document) {
12503
12698
  references.set(bindingId, (references.get(bindingId) ?? 0) + 1);
12504
12699
  };
12505
12700
  for (const node of Object.values(document.graph.nodes)) {
12506
- if (!("inputs" in node)) continue;
12701
+ if (isTriggerNode(node)) continue;
12507
12702
  const inputs = Object.values(nodeInputMappings(node));
12508
12703
  for (const mapping of inputs) {
12509
12704
  if (mapping.kind != "sources") continue;
@@ -12512,6 +12707,40 @@ function bindingReferences(document) {
12512
12707
  }
12513
12708
  return references;
12514
12709
  }
12710
+ /** Edit the workflow input contract and preserve references on a single-field rename. */
12711
+ function updateStartInputDefs(content, nodeId, value) {
12712
+ const node = content.document.graph.nodes[nodeId];
12713
+ if (node?.kind != "start") throw new TypeError("Expected a Start node.");
12714
+ const previous = node.inputDefs;
12715
+ if (dequal(previous, value)) return [];
12716
+ const operations = [{
12717
+ kind: "graph.node.replace",
12718
+ nodeId,
12719
+ before: node,
12720
+ node: {
12721
+ ...node,
12722
+ inputDefs: value
12723
+ }
12724
+ }];
12725
+ const rename = renamedPort(previous, value);
12726
+ if (rename != null) {
12727
+ const instances = /* @__PURE__ */ new Set([nodeId]);
12728
+ for (const [id, downstream] of Object.entries(content.document.graph.nodes)) {
12729
+ if (isTriggerNode(downstream)) continue;
12730
+ for (const [handle, before] of Object.entries(nodeInputMappings(downstream))) {
12731
+ const mapping = renameOutputMapping(before, instances, rename);
12732
+ if (before !== mapping) operations.push({
12733
+ before,
12734
+ kind: "graph.node.input.set",
12735
+ nodeId: id,
12736
+ handle,
12737
+ value: mapping
12738
+ });
12739
+ }
12740
+ }
12741
+ }
12742
+ return operations;
12743
+ }
12515
12744
  function defaultInputs(ports) {
12516
12745
  return Object.fromEntries(ports.flatMap((port) => "handle" in port && Object.hasOwn(port, "value") ? [[port.handle, {
12517
12746
  kind: "value",
@@ -12524,6 +12753,112 @@ function llmInputValue(values, handle, fallback) {
12524
12753
  function createDecisionTask(identity, name = "AI Decision", questions) {
12525
12754
  return createManagedTask(identity, decisionTask(questions, name));
12526
12755
  }
12756
+ /** Edit an Outputs node's definitions and mappings as one undoable change. */
12757
+ function updateOutputsDefs(content, nodeId, value, outputMappings) {
12758
+ const node = content.document.graph.nodes[nodeId];
12759
+ if (node?.kind != "outputs") throw new TypeError("Expected an Outputs node.");
12760
+ const mappings = outputMappings ?? remapInputMappings(node.outputMappings, value, renamedPort(node.outputDefs, value));
12761
+ const next = {
12762
+ ...node,
12763
+ outputDefs: value,
12764
+ outputMappings: mappings
12765
+ };
12766
+ return dequal(node, next) ? [] : cleanVariableBindings(content, [{
12767
+ kind: "graph.node.replace",
12768
+ nodeId,
12769
+ before: node,
12770
+ node: next
12771
+ }]);
12772
+ }
12773
+ function renameFlowOutputSources(content, nodeIds, previous, next) {
12774
+ const rename = renamedPort(previous, next);
12775
+ if (rename == null) return [];
12776
+ return Object.entries(content.document.graph.nodes).flatMap(([nodeId, node]) => {
12777
+ if (node.kind != "outputs") return [];
12778
+ const outputMappings = Object.fromEntries(Object.entries(node.outputMappings).map(([name, mapping]) => [name, renameOutputMapping(mapping, nodeIds, rename)]));
12779
+ return dequal(node.outputMappings, outputMappings) ? [] : [{
12780
+ kind: "graph.node.replace",
12781
+ nodeId,
12782
+ before: node,
12783
+ node: {
12784
+ ...node,
12785
+ outputMappings
12786
+ }
12787
+ }];
12788
+ });
12789
+ }
12790
+ //#endregion
12791
+ //#region src/workflow/common/workflow.ts
12792
+ var portSchema = object$1({
12793
+ handle: string().min(1),
12794
+ jsonSchema: json$5(),
12795
+ nullable: boolean(),
12796
+ description: string().optional()
12797
+ });
12798
+ strictObject({
12799
+ inputs: array(portSchema).nullable(),
12800
+ outputs: array(portSchema).nullable()
12801
+ });
12802
+ object$1({
12803
+ version: literal(1),
12804
+ flowId: string().min(1),
12805
+ name: string(),
12806
+ revisionId: string().min(1),
12807
+ publicationId: string().min(1),
12808
+ inputs: array(portSchema),
12809
+ outputs: array(portSchema).nullable()
12810
+ });
12811
+ /** A selected target is durable even before its callable interface is available. */
12812
+ function workflowSelectionTask(candidate, contract, previous) {
12813
+ if (contract != null) return workflowTask(contract, candidate.name);
12814
+ if (previous?.executor.kind == "workflow" && previous.executor.flowId == candidate.flowId) return previous;
12815
+ return {
12816
+ name: candidate.name,
12817
+ inputs: [],
12818
+ outputs: [],
12819
+ executor: {
12820
+ kind: "workflow",
12821
+ flowId: candidate.flowId,
12822
+ revisionId: ""
12823
+ }
12824
+ };
12825
+ }
12826
+ function workflowTask(contract, name = contract.name) {
12827
+ return {
12828
+ name,
12829
+ executor: {
12830
+ kind: "workflow",
12831
+ flowId: contract.flowId,
12832
+ revisionId: contract.revisionId
12833
+ },
12834
+ inputs: contract.inputs,
12835
+ outputs: contract.outputs ?? []
12836
+ };
12837
+ }
12838
+ /** Refresh capability ports by exact name; removed outputs remain unresolved at consumers. */
12839
+ function withWorkflowTask(node, task) {
12840
+ return {
12841
+ ...node,
12842
+ task,
12843
+ inputs: Object.fromEntries(Object.entries(node.inputs).filter(([handle]) => task.inputs.some((port) => "handle" in port && port.handle == handle)))
12844
+ };
12845
+ }
12846
+ object$1({
12847
+ version: literal(1),
12848
+ direction: _enum(["incoming", "outgoing"]),
12849
+ total: int().nonnegative(),
12850
+ nextOffset: int().nonnegative().optional(),
12851
+ references: array(object$1({
12852
+ flowId: string(),
12853
+ name: string().nullable(),
12854
+ available: boolean(),
12855
+ draft: boolean(),
12856
+ live: object$1({
12857
+ publicationId: string(),
12858
+ enabled: boolean()
12859
+ }).nullable()
12860
+ }))
12861
+ });
12527
12862
  //#endregion
12528
12863
  //#region src/control/common/authoringCondition.ts
12529
12864
  /** Preserve empty groups in invalid drafts; do not turn them into unconditional branches. */
@@ -12640,8 +12975,9 @@ function portField(ports, path, parent) {
12640
12975
  }
12641
12976
  }
12642
12977
  /** Accept a decoded JSON Pointer, including or omitting its initial empty component. */
12643
- function authoringDiagnosticField(_content, node, parts) {
12978
+ function authoringDiagnosticField(node, parts) {
12644
12979
  const path = parts[0] == "" ? parts.slice(1) : parts;
12980
+ if (node == null) return "config";
12645
12981
  if (path[0] == "modules") return "code";
12646
12982
  let location = path[0] == "document" && path[1] == "graph" && path[2] == "nodes" ? path.slice(4) : path;
12647
12983
  const inlineDefinition = node.kind == "task" && location[0] == "task";
@@ -12649,6 +12985,9 @@ function authoringDiagnosticField(_content, node, parts) {
12649
12985
  if (location.length == 0) return "config";
12650
12986
  const head = location[0];
12651
12987
  if (!inlineDefinition && metadata.has(head)) return location.join(".");
12988
+ if (node.kind == "start" && head == "inputDefs") return portField(node.inputDefs, location.slice(1), "config.inputDefs");
12989
+ if (node.kind == "outputs" && head == "outputDefs") return portField(node.outputDefs, location.slice(1), "config.outputDefs");
12990
+ if (node.kind == "outputs" && head == "outputMappings") return ["inputs", ...location.slice(1)].join(".");
12652
12991
  if (head == "prompt") return "prompt";
12653
12992
  if (head == "inputs" && !inlineDefinition) {
12654
12993
  if (node.kind == "condition" && location[1] != null) {
@@ -12695,6 +13034,7 @@ function authoringDiagnosticField(_content, node, parts) {
12695
13034
  const field = location[1];
12696
13035
  if (field == null || field == "kind") return "config";
12697
13036
  if (field == "prompt") return "prompt";
13037
+ if (executor?.kind == "workflow" && field == "revisionId") return "config.flowId";
12698
13038
  if (executor?.kind == "openapi") {
12699
13039
  if (field == "document") return "config";
12700
13040
  if (field == "auth") return "config.authentication";
@@ -12728,6 +13068,7 @@ function authoringDiagnosticField(_content, node, parts) {
12728
13068
  case "condition": return head == "cases" || head == "matchMode" ? ["config", ...conditionConfigurationFieldPath(node, location)].join(".") : "config";
12729
13069
  case "wait":
12730
13070
  case "approval": return head == "inputDefinitions" ? portField(node.inputDefinitions, location.slice(1), "config.inputs") : "config";
13071
+ case "start": return "config";
12731
13072
  case "webhook":
12732
13073
  if (head == "bodyFields") return portField(node.bodyFields, location.slice(1), "config.body");
12733
13074
  return head == "method" || head == "options" ? ["config", ...location].join(".") : "config";
@@ -12843,6 +13184,7 @@ async function prepareAgentTools(tools, previous, action, id) {
12843
13184
  /** Shared business configuration for authoring and published entry inspection. */
12844
13185
  function triggerConfiguration(node) {
12845
13186
  switch (node.kind) {
13187
+ case "start": return { inputDefs: fieldsView(node.inputDefs) };
12846
13188
  case "manual": return {};
12847
13189
  case "webhook": return {
12848
13190
  body: fieldsView(node.bodyFields),
@@ -12895,7 +13237,7 @@ function inputMappings(node) {
12895
13237
  }
12896
13238
  function typeOf(node) {
12897
13239
  const task = taskAt(node);
12898
- return node.kind != "task" ? node.kind : task != null && "executor" in task ? task.executor.kind : "code";
13240
+ return node.kind == "manual" ? "start" : node.kind != "task" ? node.kind : task != null && "executor" in task ? task.executor.kind : "code";
12899
13241
  }
12900
13242
  function outwardSource(content, value) {
12901
13243
  if (Array.isArray(value)) return value.map((v) => outwardSource(content, v));
@@ -12952,6 +13294,7 @@ function authoringNode(content, ref) {
12952
13294
  ...llmConfigurationView(task),
12953
13295
  inputs: fieldsView([...task.inputs, ...node.kind == "task" ? node.additionalInputs ?? [] : []].filter((port) => !("handle" in port) || !llmReservedInputs.includes(port.handle)))
12954
13296
  };
13297
+ else if (task.executor.kind == "workflow") config = { flowId: task.executor.flowId };
12955
13298
  else if (task.executor.kind == "openapi") config = { ...openApiConfigView(task.executor) };
12956
13299
  } else if (node.kind == "task" && "moduleId" in node.task) {
12957
13300
  config = {
@@ -12961,6 +13304,9 @@ function authoringNode(content, ref) {
12961
13304
  };
12962
13305
  texts.code = content.modules[node.task.moduleId]?.source ?? "";
12963
13306
  } else switch (node.kind) {
13307
+ case "outputs":
13308
+ config = { outputDefs: fieldsView(node.outputDefs) };
13309
+ break;
12964
13310
  case "condition":
12965
13311
  config = { ...conditionConfigurationView(node, (value) => outwardSource(content, value)) };
12966
13312
  break;
@@ -12976,6 +13322,9 @@ function authoringNode(content, ref) {
12976
13322
  texts.prompt = node.prompt;
12977
13323
  break;
12978
13324
  case "manual":
13325
+ config = {};
13326
+ break;
13327
+ case "start":
12979
13328
  case "webhook":
12980
13329
  case "cron":
12981
13330
  case "error":
@@ -13127,9 +13476,11 @@ function clearPath(value, path) {
13127
13476
  }
13128
13477
  async function compileAuthoring(base, request, host) {
13129
13478
  const parsed = authoringRequestSchema.parse(request);
13130
- let content = base, index = 0, sequence = 0;
13479
+ const upgraded = upgradeRevisionContent(base);
13480
+ let content = upgraded, index = 0, sequence = 0;
13131
13481
  const operations = [], aliases = {};
13132
13482
  const touchedModules = /* @__PURE__ */ new Set();
13483
+ const explicitMessages = /* @__PURE__ */ new Set();
13133
13484
  function fresh(label) {
13134
13485
  return host.id(`${index}:${label}:${sequence++}`);
13135
13486
  }
@@ -13174,12 +13525,16 @@ async function compileAuthoring(base, request, host) {
13174
13525
  }
13175
13526
  function replace(ref, node) {
13176
13527
  const before = nodeAt(content, ref);
13177
- if (!dequal(before, node)) apply([{
13178
- kind: "graph.node.replace",
13179
- nodeId: ref,
13180
- before,
13181
- node
13182
- }]);
13528
+ if (!dequal(before, node)) {
13529
+ const previous = before.kind == "task" ? before.task.outputs : before.kind == "value" ? before.values : [];
13530
+ const next = node.kind == "task" ? node.task.outputs : node.kind == "value" ? node.values : [];
13531
+ apply([{
13532
+ kind: "graph.node.replace",
13533
+ nodeId: ref,
13534
+ before,
13535
+ node
13536
+ }, ...node.kind == "task" && "executor" in node.task && node.task.executor.kind == "workflow" ? [] : renameFlowOutputSources(content, /* @__PURE__ */ new Set([ref]), previous, next)]);
13537
+ }
13183
13538
  }
13184
13539
  function taskNode(ref, task) {
13185
13540
  const node = nodeAt(content, ref);
@@ -13203,6 +13558,14 @@ async function compileAuthoring(base, request, host) {
13203
13558
  outputs: Object.entries(action.outputs).map(([handle, port]) => Object.assign({ handle }, port))
13204
13559
  };
13205
13560
  }
13561
+ async function resolveWorkflow(flowId, name, previous) {
13562
+ if (host.workflow == null) fail("workflow.unavailable", "Workflow calls are unavailable.");
13563
+ const target = await host.workflow(flowId);
13564
+ return "inputs" in target ? workflowTask(target, name) : workflowSelectionTask({
13565
+ ...target,
13566
+ name
13567
+ }, void 0, previous);
13568
+ }
13206
13569
  async function configure(ref, patch = {}, clear = []) {
13207
13570
  const node = nodeAt(content, ref), view = authoringNode(content, ref), type = view.type;
13208
13571
  const update = record(merge({
@@ -13224,12 +13587,19 @@ async function compileAuthoring(base, request, host) {
13224
13587
  ...rest,
13225
13588
  ...metadata
13226
13589
  };
13227
- if ("inputs" in node) {
13590
+ if (!isTriggerNode(node)) {
13228
13591
  const clean = { ...next };
13229
13592
  if (!Object.hasOwn(update, "timeoutMs")) delete clean.timeoutMs;
13230
13593
  if (!Object.hasOwn(update, "maxExecutions")) delete clean.maxExecutions;
13231
13594
  next = clean;
13232
13595
  } else if (update.timeoutMs != null || update.maxExecutions != null) fail("node.invalid-field", "Trigger nodes do not have execution limits.");
13596
+ if (node.kind == "start" || node.kind == "outputs") {
13597
+ replace(ref, next);
13598
+ const ports = fieldsToPorts(node.kind == "start" ? config.inputDefs : config.outputDefs, node.kind == "start" ? node.inputDefs : node.outputDefs).filter((port) => "handle" in port);
13599
+ const changes = node.kind == "start" ? updateStartInputDefs(content, ref, ports) : updateOutputsDefs(content, ref, ports);
13600
+ if (changes.length > 0) apply(changes);
13601
+ return;
13602
+ }
13233
13603
  function taskInputs(task, reserved = []) {
13234
13604
  if (node.kind != "task") throw new Error("Expected a task.");
13235
13605
  const fields = record(config.inputs);
@@ -13265,7 +13635,16 @@ async function compileAuthoring(base, request, host) {
13265
13635
  } else if (node.kind == "task" && "executor" in node.task) {
13266
13636
  const before = node.task;
13267
13637
  let task;
13268
- if (type == "connector") {
13638
+ if (type == "workflow") {
13639
+ task = before.executor.kind == "workflow" && before.executor.flowId == config.flowId ? {
13640
+ ...before,
13641
+ name: String(update.name)
13642
+ } : await resolveWorkflow(String(config.flowId), String(update.name));
13643
+ next = withWorkflowTask({
13644
+ ...node,
13645
+ ...metadata
13646
+ }, task);
13647
+ } else if (type == "connector") {
13269
13648
  if (before.executor.kind == "connector" && config.action == before.executor.action) {
13270
13649
  const { connectionId: _connectionId, ...executor } = before.executor;
13271
13650
  task = {
@@ -13439,6 +13818,7 @@ async function compileAuthoring(base, request, host) {
13439
13818
  });
13440
13819
  }
13441
13820
  async function setInput(ref, input, value) {
13821
+ if (input == "message") explicitMessages.add(ref);
13442
13822
  const node = nodeAt(content, ref);
13443
13823
  if (node.kind == "condition") fail("input.unsupported", "Edit the branch condition operands through config.branches.", {
13444
13824
  node: ref,
@@ -13504,6 +13884,18 @@ async function compileAuthoring(base, request, host) {
13504
13884
  for (const edit of parsed.edits) {
13505
13885
  try {
13506
13886
  switch (edit.op) {
13887
+ case "node.refresh": {
13888
+ const ref = resolve(edit.node);
13889
+ const node = nodeAt(content, ref);
13890
+ if (node.kind != "task" || !("executor" in node.task) || node.task.executor.kind != "workflow") fail("node.invalid-type", "Only workflow call nodes support refresh.");
13891
+ apply([{
13892
+ kind: "graph.node.replace",
13893
+ nodeId: ref,
13894
+ before: node,
13895
+ node: withWorkflowTask(node, await resolveWorkflow(node.task.executor.flowId, node.name ?? node.task.name, node.task))
13896
+ }]);
13897
+ break;
13898
+ }
13507
13899
  case "node.add": {
13508
13900
  if (Object.hasOwn(aliases, edit.as)) fail("node.alias-duplicate", `Duplicate alias ${edit.as}.`);
13509
13901
  const nodeId = host.id(`node:${edit.as}`), identity = {
@@ -13514,6 +13906,21 @@ async function compileAuthoring(base, request, host) {
13514
13906
  const config = edit.config ?? {};
13515
13907
  let changes;
13516
13908
  switch (edit.type) {
13909
+ case "workflow":
13910
+ changes = createManagedTask(identity, await resolveWorkflow(String(authoringConfigurations.workflow.parse(config).flowId), name));
13911
+ break;
13912
+ case "outputs":
13913
+ changes = [{
13914
+ kind: "graph.node.create",
13915
+ nodeId,
13916
+ node: {
13917
+ outputDefs: [],
13918
+ outputMappings: {},
13919
+ kind: "outputs",
13920
+ name
13921
+ }
13922
+ }];
13923
+ break;
13517
13924
  case "code":
13518
13925
  changes = createCodeTask(identity, name, void 0, {
13519
13926
  inputs: [],
@@ -13566,6 +13973,7 @@ async function compileAuthoring(base, request, host) {
13566
13973
  node: {
13567
13974
  kind: edit.type,
13568
13975
  name,
13976
+ ...edit.type == "start" ? { inputDefs: [] } : {},
13569
13977
  ...edit.type == "cron" ? { cronTimes: [{
13570
13978
  type: "every",
13571
13979
  unit: "hour",
@@ -13615,11 +14023,8 @@ async function compileAuthoring(base, request, host) {
13615
14023
  target: to,
13616
14024
  ...edit.branch == null ? {} : { sourceHandle: edit.branch }
13617
14025
  };
13618
- const exists = content.document.graph.edges.some((e) => dequal(e, edge));
13619
- if (edit.op == "edge.connect" != exists) apply([{
13620
- kind: edit.op == "edge.connect" ? "graph.edge.connect" : "graph.edge.disconnect",
13621
- edge
13622
- }]);
14026
+ const changes = edit.op == "edge.connect" ? connect(content, edge) : disconnect(content, edge);
14027
+ apply(explicitMessages.has(to) ? changes.filter((change) => change.kind != "graph.node.input.set") : changes);
13623
14028
  break;
13624
14029
  }
13625
14030
  case "text.set":
@@ -13649,10 +14054,10 @@ async function compileAuthoring(base, request, host) {
13649
14054
  kind: "module.delete",
13650
14055
  moduleId
13651
14056
  }]);
13652
- const cleaned = cleanVariableBindings(base, operations);
14057
+ const cleaned = cleanVariableBindings(upgraded, operations);
13653
14058
  return {
13654
14059
  operations: cleaned,
13655
- content: cleaned.length == 0 ? base : applyFlowChanges(base, cleaned),
14060
+ content: cleaned.length == 0 ? upgraded : applyFlowChanges(upgraded, cleaned),
13656
14061
  nodes: aliases
13657
14062
  };
13658
14063
  }
@@ -13675,7 +14080,7 @@ function authoringDiagnostics(content, diagnostics) {
13675
14080
  code: diagnostic.code,
13676
14081
  message,
13677
14082
  nodes: affected.map(([id]) => id),
13678
- field: affected[0] == null ? "config" : authoringDiagnosticField(content, affected[0][1], parts),
14083
+ field: authoringDiagnosticField(affected[0]?.[1], parts),
13679
14084
  ...diagnostic.line ? {
13680
14085
  line: diagnostic.line,
13681
14086
  column: diagnostic.column
@@ -13757,7 +14162,7 @@ var eventSourceRevisionSchema = strictObject({
13757
14162
  //#endregion
13758
14163
  //#region src/control/common/authoringExamples.ts
13759
14164
  var descriptions = {
13760
- "manual": "A Manual start node.",
14165
+ "start": "A Start node with a required message parameter. Supply it through trigger.outputs.",
13761
14166
  "error": "A Flow Error node. Select upstream Flows, then publish and enable this Flow to listen for failures in their automatic runs.",
13762
14167
  "webhook": "A Webhook start node.",
13763
14168
  "cron": "An hourly scheduled start node.",
@@ -13805,11 +14210,16 @@ function authoringExample(name) {
13805
14210
  } } } } } } } }
13806
14211
  }, "https://api.example.com/openapi.json", "/items", "get")));
13807
14212
  break;
13808
- case "manual":
13809
- operations = createBuiltinTrigger("start", {
13810
- kind: "manual",
14213
+ case "start":
14214
+ operations = [...createBuiltinTrigger("start", {
14215
+ inputDefs: [{
14216
+ handle: "message",
14217
+ jsonSchema: { type: "string" },
14218
+ nullable: false
14219
+ }],
14220
+ kind: "start",
13811
14221
  name: "Start"
13812
- });
14222
+ })];
13813
14223
  break;
13814
14224
  case "webhook":
13815
14225
  operations = createBuiltinTrigger("start", {
@@ -14069,6 +14479,10 @@ var schemas = {
14069
14479
  expectedRevisionId: id,
14070
14480
  version
14071
14481
  }),
14482
+ upgradeDraft: strictObject({
14483
+ expectedRevisionId: id,
14484
+ version
14485
+ }),
14072
14486
  setEnabled: strictObject({
14073
14487
  enabled: boolean(),
14074
14488
  expectedPublicationId: id,
@@ -14165,6 +14579,7 @@ var controlRequests = {
14165
14579
  };
14166
14580
  },
14167
14581
  repairDraft: decoder(schemas.repairDraft),
14582
+ upgradeDraft: decoder(schemas.upgradeDraft),
14168
14583
  setEnabled: decoder(schemas.setEnabled),
14169
14584
  updatePresentation: decoder(schemas.updatePresentation),
14170
14585
  checkFlow: decoder(schemas.checkFlow),
@@ -14193,4 +14608,4 @@ function controlRequestSchema(name) {
14193
14608
  return schema;
14194
14609
  }
14195
14610
  //#endregion
14196
- export { AuthoringError, authoringCheckResponse, authoringCheckSchema, authoringConfigurations, authoringDiagnosticSchema, authoringDiagnostics, authoringEditResponse, authoringEditSchema, authoringExample, authoringExamples, authoringNode, authoringReadResponse, authoringReadSchema, authoringRequestContract, authoringRequestSchema, authoringSchema, authoringSchemaQuery, authoringSearchResponse, authoringSearchSchema, authoringSourceSchema, authoringTypes, canvasCommandSchema, compileAuthoring, controlRequestSchema, controlRequests, decodeDraftOperations, draftOperationsSchema, readAuthoring, resolveDraftOperations, searchAuthoring, waitActionBodySchema };
14611
+ export { AuthoringError, authoringCheckResponse, authoringCheckSchema, authoringConfigurations, authoringDiagnosticSchema, authoringDiagnostics, authoringEditResponse, authoringEditSchema, authoringExample, authoringExamples, authoringNode, authoringReadResponse, authoringReadSchema, authoringRequestContract, authoringRequestSchema, authoringSchema, authoringSchemaQuery, authoringSearchResponse, authoringSearchSchema, authoringSourceSchema, authoringTypes, canvasCommandSchema, compileAuthoring, controlRequestSchema, controlRequests, decodeDraftOperations, draftOperationsSchema, flowInputFields, flowInputFieldsView, flowOutputFields, readAuthoring, resolveDraftOperations, searchAuthoring, waitActionBodySchema };