@oomol-lab/open-flow 0.1.0-beta.65 → 0.1.0-beta.67

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 (54) hide show
  1. package/dist/browser/{createResourceDialog-BAJXbzNH.js → createResourceDialog-BQVD8Rqb.js} +2 -2
  2. package/dist/browser/{icons-Db2Jb2iX.js → dialog-CS2Vt2if.js} +5736 -5621
  3. package/dist/browser/event-sources.d.ts +4 -1
  4. package/dist/browser/flow-authoring-node.d.ts +14 -3
  5. package/dist/browser/flow-authoring.js +120 -24
  6. package/dist/browser/flow-change-schema.d.ts +3 -1
  7. package/dist/browser/flow-change.d.ts +15 -3
  8. package/dist/browser/flow-change.js +117 -21
  9. package/dist/browser/{flowChanges-DkvG5uDq.js → flowChanges-VB9Y4iy7.js} +3423 -2380
  10. package/dist/browser/{flowRunInputEditorStore-B2Rw4VsT.js → flowRunInputEditorStore-DJqmR6Qh.js} +3 -2
  11. package/dist/browser/{flowWorkspace-BEp-lxqF.js → flowWorkspace-C1hlTnZq.js} +1410 -799
  12. package/dist/browser/preview.css +273 -119
  13. package/dist/browser/preview.js +17118 -15810
  14. package/dist/browser/theme.css +1 -0
  15. package/dist/browser/ui.css +119 -7
  16. package/dist/browser/ui.js +8 -5
  17. package/dist/browser/workbench-contract.d.ts +1 -1
  18. package/dist/browser/workbench.css +282 -162
  19. package/dist/browser/workbench.d.ts +0 -1
  20. package/dist/browser/workbench.js +503 -173
  21. package/dist/browser/{workbenchSelect-C-jf6NIM.js → workbenchSelect-CpXhjUou.js} +1 -1
  22. package/dist/command/index.js +49 -49
  23. package/dist/common/authoring.d.ts +7 -5
  24. package/dist/common/authoringExamples.d.ts +4 -4
  25. package/dist/common/authoringFields.d.ts +20 -0
  26. package/dist/common/authoringSchema.d.ts +404 -15
  27. package/dist/common/control-api-conformance.js +415 -146
  28. package/dist/common/control-api.d.ts +67 -8
  29. package/dist/common/control-api.js +3587 -3443
  30. package/dist/common/control-requests.d.ts +10 -3
  31. package/dist/common/control-requests.js +425 -49
  32. package/dist/common/decision.js +33 -7
  33. package/dist/common/flow-encoding.d.ts +4 -2
  34. package/dist/common/flow-encoding.js +151 -14
  35. package/dist/common/flow-graph.d.ts +1 -1
  36. package/dist/common/flow-semantics.d.ts +12 -2
  37. package/dist/common/flow-semantics.js +157 -41
  38. package/dist/common/integration-trigger.js +33 -7
  39. package/dist/common/liveDetails.d.ts +26 -11
  40. package/dist/common/mcp.d.ts +6 -3
  41. package/dist/common/mcp.js +219 -90
  42. package/dist/common/openapi.js +33 -7
  43. package/dist/common/poll-trigger.js +33 -7
  44. package/dist/common/run-events.d.ts +2 -0
  45. package/dist/common/run-events.js +9 -3
  46. package/dist/common/scheduler.d.ts +10 -1
  47. package/dist/common/scheduler.js +172 -49
  48. package/dist/common/trigger-contract.d.ts +2 -0
  49. package/dist/common/webhook-trigger.js +33 -7
  50. package/dist/common/workflow.d.ts +93 -0
  51. package/dist/common/workflow.js +10492 -0
  52. package/package.json +5 -1
  53. package/skills/open-flow/SKILL.md +9 -0
  54. package/skills/open-flow/references/flow-authoring.md +28 -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",
@@ -6886,7 +6887,7 @@ function decodeConnectorCapabilities(value) {
6886
6887
  const actions = source.actions.map((entry) => {
6887
6888
  if (entry == null || typeof entry != "object" || Array.isArray(entry)) throw new TypeError("Invalid Connector Action.");
6888
6889
  const action = entry;
6889
- if (Object.keys(action).some((key) => !["action", "connectionId"].includes(key)) || typeof action.action != "string" || !/^[A-Za-z0-9_-]+\.[A-Za-z0-9_.-]+$/.test(action.action) || Object.hasOwn(action, "connectionId") && (typeof action.connectionId != "string" || action.connectionId.length == 0)) throw new TypeError("Invalid Connector Action permission.");
6890
+ if (Object.keys(action).some((key) => !["action", "connectionId"].includes(key)) || typeof action.action != "string" || !/^[A-Za-z0-9_-]+\.[A-Za-z0-9_.-]+$/.test(action.action) || Object.hasOwn(action, "connectionId") && typeof action.connectionId != "string") throw new TypeError("Invalid Connector Action permission.");
6890
6891
  return action.connectionId == null ? { action: action.action } : {
6891
6892
  action: action.action,
6892
6893
  connectionId: action.connectionId
@@ -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
@@ -10367,6 +10423,7 @@ function webhookSupportsBody(method) {
10367
10423
  return method !== "GET";
10368
10424
  }
10369
10425
  var text$1 = string();
10426
+ 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.");
10370
10427
  var json$4 = json$5();
10371
10428
  var strings = array(text$1);
10372
10429
  var port = object$1({
@@ -10375,6 +10432,7 @@ var port = object$1({
10375
10432
  nullable: boolean(),
10376
10433
  handle: text$1
10377
10434
  });
10435
+ var workflowInputDefs = array(port.strict());
10378
10436
  var input = port.extend({ value: json$4.optional() });
10379
10437
  var group = object$1({
10380
10438
  collapsed: boolean().optional(),
@@ -10421,7 +10479,7 @@ var capability = union([
10421
10479
  mode: literal("independent"),
10422
10480
  actions: array(strictObject({
10423
10481
  action: text$1,
10424
- connectionId: text$1.optional()
10482
+ connectionId: actionConnection.optional()
10425
10483
  }))
10426
10484
  }),
10427
10485
  strictObject({
@@ -10481,7 +10539,7 @@ var managedFields = object$1({
10481
10539
  object$1({
10482
10540
  kind: literal("connector"),
10483
10541
  action: text$1,
10484
- connectionId: text$1.optional(),
10542
+ connectionId: actionConnection.optional(),
10485
10543
  outputMode: literal("value").optional()
10486
10544
  }),
10487
10545
  object$1({
@@ -10521,17 +10579,22 @@ var managedFields = object$1({
10521
10579
  name: text$1,
10522
10580
  description: text$1,
10523
10581
  action: text$1,
10524
- connectionId: text$1.optional(),
10582
+ connectionId: actionConnection.optional(),
10525
10583
  approval: boolean(),
10526
10584
  inputs: array(input.extend({ source: agentInput }))
10527
10585
  })),
10528
10586
  notification: object$1({
10529
10587
  action: text$1,
10530
- connectionId: text$1.optional(),
10588
+ connectionId: actionConnection.optional(),
10531
10589
  inputDefinitions: array(input),
10532
10590
  messageHandle: text$1,
10533
10591
  inputs: record$3(text$1, agentValue)
10534
10592
  }).optional()
10593
+ }),
10594
+ strictObject({
10595
+ kind: literal("workflow"),
10596
+ flowId: text$1,
10597
+ revisionId: text$1
10535
10598
  })
10536
10599
  ])
10537
10600
  });
@@ -10640,6 +10703,12 @@ var base = {
10640
10703
  timeoutMs: number().optional()
10641
10704
  };
10642
10705
  var node = union([
10706
+ strictObject({
10707
+ ...base,
10708
+ kind: literal("outputs"),
10709
+ outputDefs: array(port.strict()),
10710
+ outputMappings: inputs$1
10711
+ }).omit({ inputs: true }),
10643
10712
  object$1({
10644
10713
  ...base,
10645
10714
  inputs: record$3(text$1, never()),
@@ -10672,6 +10741,11 @@ var node = union([
10672
10741
  ...trigger$1,
10673
10742
  kind: literal("manual")
10674
10743
  }),
10744
+ strictObject({
10745
+ ...trigger$1,
10746
+ kind: literal("start"),
10747
+ inputDefs: workflowInputDefs
10748
+ }),
10675
10749
  strictObject({
10676
10750
  ...trigger$1,
10677
10751
  kind: literal("error"),
@@ -10751,35 +10825,51 @@ var module = object$1({
10751
10825
  imports: strings,
10752
10826
  source: text$1
10753
10827
  });
10754
- var document = preprocess(rejectRetiredDefinitions, object$1({
10828
+ var document = preprocess(normalizeDocument, object$1({
10755
10829
  bindings: record$3(text$1, binding),
10756
10830
  graph
10757
10831
  }));
10758
- object$1({
10832
+ var revision = object$1({
10759
10833
  modelVersion: union([
10760
10834
  literal(2),
10761
10835
  literal(4),
10762
10836
  literal(5),
10763
- literal(6)
10837
+ literal(6),
10838
+ literal(7),
10839
+ literal(8)
10764
10840
  ]),
10765
10841
  document,
10766
10842
  modules: record$3(text$1, module)
10767
- }).extend({
10843
+ });
10844
+ revision.extend({
10768
10845
  kind: literal("open-flow-flow-revision"),
10769
10846
  version: literal(1)
10770
10847
  });
10771
- function rejectRetiredDefinitions(value) {
10848
+ function normalizeDocument(value) {
10772
10849
  const candidate = record$2(value);
10773
10850
  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
10851
  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
10852
  const subflows = candidate.subflows;
10776
10853
  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
10854
  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.");
10855
+ if ([
10856
+ "inputDefs",
10857
+ "outputDefs",
10858
+ "outputMappings"
10859
+ ].some((field) => Object.hasOwn(candidate, field))) throw new TypeError("Workflow interface configuration must belong to Start and Outputs nodes.");
10860
+ 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
10861
  return value;
10779
10862
  }
10780
10863
  function record$2(value) {
10781
10864
  return value != null && typeof value == "object" && !Array.isArray(value) ? value : {};
10782
10865
  }
10866
+ function decodeRevisionContent(value) {
10867
+ checkJsonDepth(value);
10868
+ const content = revision.parse(value);
10869
+ checkModelVersion(content);
10870
+ assertOpenApiAuthBindings(content.document);
10871
+ return content;
10872
+ }
10783
10873
  var shapes = {
10784
10874
  "graph.trigger.sources.set": {
10785
10875
  nodeId: text$1,
@@ -10956,6 +11046,12 @@ function changeOperationsSchema(kind) {
10956
11046
  if (schema == null) throw new TypeError(`Unknown operation ${JSON.stringify(kind)}.`);
10957
11047
  return toJSONSchema(schema, { io: "input" });
10958
11048
  }
11049
+ function checkModelVersion(content) {
11050
+ 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.");
11051
+ 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.");
11052
+ 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.");
11053
+ 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.");
11054
+ }
10959
11055
  //#endregion
10960
11056
  //#region src/control/common/authoringLlm.ts
10961
11057
  var authoringLlmConfiguration = strictObject({
@@ -11527,7 +11623,9 @@ var id$2 = string().min(1);
11527
11623
  var json$3 = json$5();
11528
11624
  var patch = record$3(id$2, json$3);
11529
11625
  var authoringTypes = [
11530
- "manual",
11626
+ "start",
11627
+ "outputs",
11628
+ "workflow",
11531
11629
  "webhook",
11532
11630
  "cron",
11533
11631
  "error",
@@ -11600,6 +11698,12 @@ var field = strictObject({
11600
11698
  description: string().optional()
11601
11699
  });
11602
11700
  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.");
11701
+ 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.");
11702
+ 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.");
11703
+ var flowInputFieldsView = record$3(id$2, field.extend({
11704
+ schema: json$3,
11705
+ nullable: boolean()
11706
+ }));
11603
11707
  var outputFields = record$3(id$2, field).describe("Code return fields by name. Omitted schema accepts any JSON; omitted nullable is true.");
11604
11708
  var expression = strictObject({
11605
11709
  left: operand,
@@ -11613,7 +11717,9 @@ var when = union([
11613
11717
  strictObject({ any: array(union([expression, all])) })
11614
11718
  ]);
11615
11719
  var authoringConfigurations = {
11616
- manual: strictObject({}),
11720
+ workflow: strictObject({ flowId: id$2 }),
11721
+ start: strictObject({ inputDefs: flowInputFields.default({}) }),
11722
+ outputs: strictObject({ outputDefs: flowOutputFields.default({}) }),
11617
11723
  error: strictObject({ sourceFlowIds: array(id$2).optional() }),
11618
11724
  webhook: authoringDefinitionSchemas.webhook.omit({ bodyFields: true }).extend({ body: inputFields }).strict(),
11619
11725
  cron: strictObject({ schedule: authoringDefinitionSchemas.schedule }),
@@ -11684,6 +11790,10 @@ var authoringEditSchema = discriminatedUnion("op", [
11684
11790
  set: updates.optional(),
11685
11791
  clear: array(array(id$2).min(1)).optional()
11686
11792
  }),
11793
+ strictObject({
11794
+ op: literal("node.refresh"),
11795
+ node: referenceSchema
11796
+ }),
11687
11797
  strictObject({
11688
11798
  op: literal("node.remove"),
11689
11799
  node: referenceSchema
@@ -11747,7 +11857,7 @@ var authoringSchemaQuery = strictObject({
11747
11857
  var requestContracts = {
11748
11858
  read: {
11749
11859
  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.",
11860
+ 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
11861
  examples: [
11752
11862
  {},
11753
11863
  {
@@ -11775,7 +11885,7 @@ var requestContracts = {
11775
11885
  },
11776
11886
  edit: {
11777
11887
  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.",
11888
+ 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
11889
  examples: [{
11780
11890
  baseRevision: "REVISION",
11781
11891
  requestId: "CREATE_REQUEST",
@@ -11783,7 +11893,7 @@ var requestContracts = {
11783
11893
  {
11784
11894
  op: "node.add",
11785
11895
  as: "start",
11786
- type: "manual",
11896
+ type: "start",
11787
11897
  name: "Start"
11788
11898
  },
11789
11899
  {
@@ -11844,7 +11954,8 @@ function authoringSchema(kind) {
11844
11954
  "unset",
11845
11955
  "default"
11846
11956
  ] : [
11847
- "manual",
11957
+ "start",
11958
+ "outputs",
11848
11959
  "error",
11849
11960
  "cron",
11850
11961
  "webhook",
@@ -11865,13 +11976,16 @@ function authoringSchema(kind) {
11865
11976
  "wait",
11866
11977
  "approval"
11867
11978
  ].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.",
11979
+ 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
11980
  example: {
11870
11981
  op: "node.add",
11871
11982
  as: "step",
11872
11983
  type: kind,
11873
11984
  name: "Step",
11874
11985
  ...{
11986
+ start: { config: { inputDefs: {} } },
11987
+ outputs: { config: { outputDefs: {} } },
11988
+ workflow: { config: { flowId: "<Flow ID>" } },
11875
11989
  connector: { config: {
11876
11990
  action: "<Action ID>",
11877
11991
  connectionId: "<Connection ID>"
@@ -12026,7 +12140,7 @@ var authoringSearchResponse = object$1({
12026
12140
  revision: id$2,
12027
12141
  data: object$1({
12028
12142
  matches: array(object$1({
12029
- node: id$2,
12143
+ node: id$2.optional(),
12030
12144
  field: id$2,
12031
12145
  line: int().optional(),
12032
12146
  excerpt: string()
@@ -12187,6 +12301,7 @@ function triggerOutputDefinitions(trigger) {
12187
12301
  switch (trigger.kind) {
12188
12302
  case "error": return errorOutputs;
12189
12303
  case "manual": return [];
12304
+ case "start": return trigger.inputDefs;
12190
12305
  case "cron": return cronOutputs;
12191
12306
  case "poll":
12192
12307
  case "integration": return trigger.definition.outputs;
@@ -12205,6 +12320,7 @@ function triggerOutputPorts(trigger) {
12205
12320
  //#region src/flow/common/graph.ts
12206
12321
  function nodeInputPorts(node) {
12207
12322
  switch (node.kind) {
12323
+ case "outputs": return portsByHandle(node.outputDefs);
12208
12324
  case "condition": return conditionInputPorts(node);
12209
12325
  case "value": return {};
12210
12326
  case "task": return portsByHandle([...node.task.inputs, ...node.additionalInputs ?? []]);
@@ -12215,6 +12331,7 @@ function nodeInputPorts(node) {
12215
12331
  case "poll":
12216
12332
  case "error":
12217
12333
  case "manual":
12334
+ case "start":
12218
12335
  case "webhook": return {};
12219
12336
  }
12220
12337
  }
@@ -12261,6 +12378,7 @@ function resolutionOutputPorts(node) {
12261
12378
  }
12262
12379
  function nodeOutputPorts(node) {
12263
12380
  switch (node.kind) {
12381
+ case "outputs":
12264
12382
  case "condition": return {};
12265
12383
  case "value": return portsByHandle(node.values);
12266
12384
  case "task": return portsByHandle(node.task.outputs);
@@ -12271,6 +12389,7 @@ function nodeOutputPorts(node) {
12271
12389
  case "poll":
12272
12390
  case "error":
12273
12391
  case "manual":
12392
+ case "start":
12274
12393
  case "webhook": return triggerOutputPorts(node);
12275
12394
  }
12276
12395
  }
@@ -12295,6 +12414,42 @@ async function imports(source) {
12295
12414
  }
12296
12415
  }
12297
12416
  //#endregion
12417
+ //#region src/flow/common/portChanges.ts
12418
+ function renamedPort(previous, next) {
12419
+ const previousNames = new Set(previous.flatMap((port) => "handle" in port ? [port.handle] : []));
12420
+ const nextNames = new Set(next.flatMap((port) => "handle" in port ? [port.handle] : []));
12421
+ const removed = [...previousNames].filter((name) => !nextNames.has(name));
12422
+ const added = [...nextNames].filter((name) => !previousNames.has(name));
12423
+ return removed.length == 1 && added.length == 1 ? [removed[0], added[0]] : void 0;
12424
+ }
12425
+ function renameOutputMapping(mapping, nodeIds, rename) {
12426
+ if (rename == null || mapping.kind != "sources") return mapping;
12427
+ const sources = mapping.sources.map((source) => source.kind == "node" && nodeIds.has(source.nodeId) && source.output == rename[0] ? {
12428
+ ...source,
12429
+ output: rename[1]
12430
+ } : source);
12431
+ return sources.every((source, index) => source === mapping.sources[index]) ? mapping : {
12432
+ kind: "sources",
12433
+ sources
12434
+ };
12435
+ }
12436
+ /** Carry saved mappings through a field rename and remove only fields absent from the new contract. */
12437
+ function remapInputMappings(mappings, ports, rename) {
12438
+ const inputs = { ...mappings };
12439
+ if (rename != null && Object.hasOwn(inputs, rename[0])) {
12440
+ Object.defineProperty(inputs, rename[1], {
12441
+ value: inputs[rename[0]],
12442
+ enumerable: true,
12443
+ configurable: true,
12444
+ writable: true
12445
+ });
12446
+ delete inputs[rename[0]];
12447
+ }
12448
+ const names = new Set(ports.flatMap((port) => "handle" in port ? [port.handle] : []));
12449
+ for (const name of Object.keys(inputs)) if (!names.has(name)) delete inputs[name];
12450
+ return inputs;
12451
+ }
12452
+ //#endregion
12298
12453
  //#region src/flow/common/nodeChanges.ts
12299
12454
  var codeTaskTemplate = `export default async function (inputs, context) {
12300
12455
  return { result: inputs.value }
@@ -12544,7 +12699,7 @@ function bindingReferences(document) {
12544
12699
  references.set(bindingId, (references.get(bindingId) ?? 0) + 1);
12545
12700
  };
12546
12701
  for (const node of Object.values(document.graph.nodes)) {
12547
- if (!("inputs" in node)) continue;
12702
+ if (isTriggerNode(node)) continue;
12548
12703
  const inputs = Object.values(nodeInputMappings(node));
12549
12704
  for (const mapping of inputs) {
12550
12705
  if (mapping.kind != "sources") continue;
@@ -12553,6 +12708,40 @@ function bindingReferences(document) {
12553
12708
  }
12554
12709
  return references;
12555
12710
  }
12711
+ /** Edit the workflow input contract and preserve references on a single-field rename. */
12712
+ function updateStartInputDefs(content, nodeId, value) {
12713
+ const node = content.document.graph.nodes[nodeId];
12714
+ if (node?.kind != "start") throw new TypeError("Expected a Start node.");
12715
+ const previous = node.inputDefs;
12716
+ if (dequal(previous, value)) return [];
12717
+ const operations = [{
12718
+ kind: "graph.node.replace",
12719
+ nodeId,
12720
+ before: node,
12721
+ node: {
12722
+ ...node,
12723
+ inputDefs: value
12724
+ }
12725
+ }];
12726
+ const rename = renamedPort(previous, value);
12727
+ if (rename != null) {
12728
+ const instances = /* @__PURE__ */ new Set([nodeId]);
12729
+ for (const [id, downstream] of Object.entries(content.document.graph.nodes)) {
12730
+ if (isTriggerNode(downstream)) continue;
12731
+ for (const [handle, before] of Object.entries(nodeInputMappings(downstream))) {
12732
+ const mapping = renameOutputMapping(before, instances, rename);
12733
+ if (before !== mapping) operations.push({
12734
+ before,
12735
+ kind: "graph.node.input.set",
12736
+ nodeId: id,
12737
+ handle,
12738
+ value: mapping
12739
+ });
12740
+ }
12741
+ }
12742
+ }
12743
+ return operations;
12744
+ }
12556
12745
  function defaultInputs(ports) {
12557
12746
  return Object.fromEntries(ports.flatMap((port) => "handle" in port && Object.hasOwn(port, "value") ? [[port.handle, {
12558
12747
  kind: "value",
@@ -12565,6 +12754,112 @@ function llmInputValue(values, handle, fallback) {
12565
12754
  function createDecisionTask(identity, name = "AI Decision", questions) {
12566
12755
  return createManagedTask(identity, decisionTask(questions, name));
12567
12756
  }
12757
+ /** Edit an Outputs node's definitions and mappings as one undoable change. */
12758
+ function updateOutputsDefs(content, nodeId, value, outputMappings) {
12759
+ const node = content.document.graph.nodes[nodeId];
12760
+ if (node?.kind != "outputs") throw new TypeError("Expected an Outputs node.");
12761
+ const mappings = outputMappings ?? remapInputMappings(node.outputMappings, value, renamedPort(node.outputDefs, value));
12762
+ const next = {
12763
+ ...node,
12764
+ outputDefs: value,
12765
+ outputMappings: mappings
12766
+ };
12767
+ return dequal(node, next) ? [] : cleanVariableBindings(content, [{
12768
+ kind: "graph.node.replace",
12769
+ nodeId,
12770
+ before: node,
12771
+ node: next
12772
+ }]);
12773
+ }
12774
+ function renameFlowOutputSources(content, nodeIds, previous, next) {
12775
+ const rename = renamedPort(previous, next);
12776
+ if (rename == null) return [];
12777
+ return Object.entries(content.document.graph.nodes).flatMap(([nodeId, node]) => {
12778
+ if (node.kind != "outputs") return [];
12779
+ const outputMappings = Object.fromEntries(Object.entries(node.outputMappings).map(([name, mapping]) => [name, renameOutputMapping(mapping, nodeIds, rename)]));
12780
+ return dequal(node.outputMappings, outputMappings) ? [] : [{
12781
+ kind: "graph.node.replace",
12782
+ nodeId,
12783
+ before: node,
12784
+ node: {
12785
+ ...node,
12786
+ outputMappings
12787
+ }
12788
+ }];
12789
+ });
12790
+ }
12791
+ //#endregion
12792
+ //#region src/workflow/common/workflow.ts
12793
+ var portSchema = object$1({
12794
+ handle: string().min(1),
12795
+ jsonSchema: json$5(),
12796
+ nullable: boolean(),
12797
+ description: string().optional()
12798
+ });
12799
+ strictObject({
12800
+ inputs: array(portSchema).nullable(),
12801
+ outputs: array(portSchema).nullable()
12802
+ });
12803
+ object$1({
12804
+ version: literal(1),
12805
+ flowId: string().min(1),
12806
+ name: string(),
12807
+ revisionId: string().min(1),
12808
+ publicationId: string().min(1),
12809
+ inputs: array(portSchema),
12810
+ outputs: array(portSchema).nullable()
12811
+ });
12812
+ /** A selected target is durable even before its callable interface is available. */
12813
+ function workflowSelectionTask(candidate, contract, previous) {
12814
+ if (contract != null) return workflowTask(contract, candidate.name);
12815
+ if (previous?.executor.kind == "workflow" && previous.executor.flowId == candidate.flowId) return previous;
12816
+ return {
12817
+ name: candidate.name,
12818
+ inputs: [],
12819
+ outputs: [],
12820
+ executor: {
12821
+ kind: "workflow",
12822
+ flowId: candidate.flowId,
12823
+ revisionId: ""
12824
+ }
12825
+ };
12826
+ }
12827
+ function workflowTask(contract, name = contract.name) {
12828
+ return {
12829
+ name,
12830
+ executor: {
12831
+ kind: "workflow",
12832
+ flowId: contract.flowId,
12833
+ revisionId: contract.revisionId
12834
+ },
12835
+ inputs: contract.inputs,
12836
+ outputs: contract.outputs ?? []
12837
+ };
12838
+ }
12839
+ /** Refresh capability ports by exact name; removed outputs remain unresolved at consumers. */
12840
+ function withWorkflowTask(node, task) {
12841
+ return {
12842
+ ...node,
12843
+ task,
12844
+ inputs: Object.fromEntries(Object.entries(node.inputs).filter(([handle]) => task.inputs.some((port) => "handle" in port && port.handle == handle)))
12845
+ };
12846
+ }
12847
+ object$1({
12848
+ version: literal(1),
12849
+ direction: _enum(["incoming", "outgoing"]),
12850
+ total: int().nonnegative(),
12851
+ nextOffset: int().nonnegative().optional(),
12852
+ references: array(object$1({
12853
+ flowId: string(),
12854
+ name: string().nullable(),
12855
+ available: boolean(),
12856
+ draft: boolean(),
12857
+ live: object$1({
12858
+ publicationId: string(),
12859
+ enabled: boolean()
12860
+ }).nullable()
12861
+ }))
12862
+ });
12568
12863
  //#endregion
12569
12864
  //#region src/control/common/authoringCondition.ts
12570
12865
  /** Preserve empty groups in invalid drafts; do not turn them into unconditional branches. */
@@ -12681,8 +12976,9 @@ function portField(ports, path, parent) {
12681
12976
  }
12682
12977
  }
12683
12978
  /** Accept a decoded JSON Pointer, including or omitting its initial empty component. */
12684
- function authoringDiagnosticField(_content, node, parts) {
12979
+ function authoringDiagnosticField(node, parts) {
12685
12980
  const path = parts[0] == "" ? parts.slice(1) : parts;
12981
+ if (node == null) return "config";
12686
12982
  if (path[0] == "modules") return "code";
12687
12983
  let location = path[0] == "document" && path[1] == "graph" && path[2] == "nodes" ? path.slice(4) : path;
12688
12984
  const inlineDefinition = node.kind == "task" && location[0] == "task";
@@ -12690,6 +12986,9 @@ function authoringDiagnosticField(_content, node, parts) {
12690
12986
  if (location.length == 0) return "config";
12691
12987
  const head = location[0];
12692
12988
  if (!inlineDefinition && metadata.has(head)) return location.join(".");
12989
+ if (node.kind == "start" && head == "inputDefs") return portField(node.inputDefs, location.slice(1), "config.inputDefs");
12990
+ if (node.kind == "outputs" && head == "outputDefs") return portField(node.outputDefs, location.slice(1), "config.outputDefs");
12991
+ if (node.kind == "outputs" && head == "outputMappings") return ["inputs", ...location.slice(1)].join(".");
12693
12992
  if (head == "prompt") return "prompt";
12694
12993
  if (head == "inputs" && !inlineDefinition) {
12695
12994
  if (node.kind == "condition" && location[1] != null) {
@@ -12736,6 +13035,7 @@ function authoringDiagnosticField(_content, node, parts) {
12736
13035
  const field = location[1];
12737
13036
  if (field == null || field == "kind") return "config";
12738
13037
  if (field == "prompt") return "prompt";
13038
+ if (executor?.kind == "workflow" && field == "revisionId") return "config.flowId";
12739
13039
  if (executor?.kind == "openapi") {
12740
13040
  if (field == "document") return "config";
12741
13041
  if (field == "auth") return "config.authentication";
@@ -12769,6 +13069,7 @@ function authoringDiagnosticField(_content, node, parts) {
12769
13069
  case "condition": return head == "cases" || head == "matchMode" ? ["config", ...conditionConfigurationFieldPath(node, location)].join(".") : "config";
12770
13070
  case "wait":
12771
13071
  case "approval": return head == "inputDefinitions" ? portField(node.inputDefinitions, location.slice(1), "config.inputs") : "config";
13072
+ case "start": return "config";
12772
13073
  case "webhook":
12773
13074
  if (head == "bodyFields") return portField(node.bodyFields, location.slice(1), "config.body");
12774
13075
  return head == "method" || head == "options" ? ["config", ...location].join(".") : "config";
@@ -12884,6 +13185,7 @@ async function prepareAgentTools(tools, previous, action, id) {
12884
13185
  /** Shared business configuration for authoring and published entry inspection. */
12885
13186
  function triggerConfiguration(node) {
12886
13187
  switch (node.kind) {
13188
+ case "start": return { inputDefs: fieldsView(node.inputDefs) };
12887
13189
  case "manual": return {};
12888
13190
  case "webhook": return {
12889
13191
  body: fieldsView(node.bodyFields),
@@ -12936,7 +13238,7 @@ function inputMappings(node) {
12936
13238
  }
12937
13239
  function typeOf(node) {
12938
13240
  const task = taskAt(node);
12939
- return node.kind != "task" ? node.kind : task != null && "executor" in task ? task.executor.kind : "code";
13241
+ return node.kind == "manual" ? "start" : node.kind != "task" ? node.kind : task != null && "executor" in task ? task.executor.kind : "code";
12940
13242
  }
12941
13243
  function outwardSource(content, value) {
12942
13244
  if (Array.isArray(value)) return value.map((v) => outwardSource(content, v));
@@ -12993,6 +13295,7 @@ function authoringNode(content, ref) {
12993
13295
  ...llmConfigurationView(task),
12994
13296
  inputs: fieldsView([...task.inputs, ...node.kind == "task" ? node.additionalInputs ?? [] : []].filter((port) => !("handle" in port) || !llmReservedInputs.includes(port.handle)))
12995
13297
  };
13298
+ else if (task.executor.kind == "workflow") config = { flowId: task.executor.flowId };
12996
13299
  else if (task.executor.kind == "openapi") config = { ...openApiConfigView(task.executor) };
12997
13300
  } else if (node.kind == "task" && "moduleId" in node.task) {
12998
13301
  config = {
@@ -13002,6 +13305,9 @@ function authoringNode(content, ref) {
13002
13305
  };
13003
13306
  texts.code = content.modules[node.task.moduleId]?.source ?? "";
13004
13307
  } else switch (node.kind) {
13308
+ case "outputs":
13309
+ config = { outputDefs: fieldsView(node.outputDefs) };
13310
+ break;
13005
13311
  case "condition":
13006
13312
  config = { ...conditionConfigurationView(node, (value) => outwardSource(content, value)) };
13007
13313
  break;
@@ -13017,6 +13323,9 @@ function authoringNode(content, ref) {
13017
13323
  texts.prompt = node.prompt;
13018
13324
  break;
13019
13325
  case "manual":
13326
+ config = {};
13327
+ break;
13328
+ case "start":
13020
13329
  case "webhook":
13021
13330
  case "cron":
13022
13331
  case "error":
@@ -13168,7 +13477,8 @@ function clearPath(value, path) {
13168
13477
  }
13169
13478
  async function compileAuthoring(base, request, host) {
13170
13479
  const parsed = authoringRequestSchema.parse(request);
13171
- let content = base, index = 0, sequence = 0;
13480
+ const upgraded = upgradeRevisionContent(base);
13481
+ let content = upgraded, index = 0, sequence = 0;
13172
13482
  const operations = [], aliases = {};
13173
13483
  const touchedModules = /* @__PURE__ */ new Set();
13174
13484
  const explicitMessages = /* @__PURE__ */ new Set();
@@ -13216,12 +13526,16 @@ async function compileAuthoring(base, request, host) {
13216
13526
  }
13217
13527
  function replace(ref, node) {
13218
13528
  const before = nodeAt(content, ref);
13219
- if (!dequal(before, node)) apply([{
13220
- kind: "graph.node.replace",
13221
- nodeId: ref,
13222
- before,
13223
- node
13224
- }]);
13529
+ if (!dequal(before, node)) {
13530
+ const previous = before.kind == "task" ? before.task.outputs : before.kind == "value" ? before.values : [];
13531
+ const next = node.kind == "task" ? node.task.outputs : node.kind == "value" ? node.values : [];
13532
+ apply([{
13533
+ kind: "graph.node.replace",
13534
+ nodeId: ref,
13535
+ before,
13536
+ node
13537
+ }, ...node.kind == "task" && "executor" in node.task && node.task.executor.kind == "workflow" ? [] : renameFlowOutputSources(content, /* @__PURE__ */ new Set([ref]), previous, next)]);
13538
+ }
13225
13539
  }
13226
13540
  function taskNode(ref, task) {
13227
13541
  const node = nodeAt(content, ref);
@@ -13245,6 +13559,14 @@ async function compileAuthoring(base, request, host) {
13245
13559
  outputs: Object.entries(action.outputs).map(([handle, port]) => Object.assign({ handle }, port))
13246
13560
  };
13247
13561
  }
13562
+ async function resolveWorkflow(flowId, name, previous) {
13563
+ if (host.workflow == null) fail("workflow.unavailable", "Workflow calls are unavailable.");
13564
+ const target = await host.workflow(flowId);
13565
+ return "inputs" in target ? workflowTask(target, name) : workflowSelectionTask({
13566
+ ...target,
13567
+ name
13568
+ }, void 0, previous);
13569
+ }
13248
13570
  async function configure(ref, patch = {}, clear = []) {
13249
13571
  const node = nodeAt(content, ref), view = authoringNode(content, ref), type = view.type;
13250
13572
  const update = record(merge({
@@ -13266,12 +13588,19 @@ async function compileAuthoring(base, request, host) {
13266
13588
  ...rest,
13267
13589
  ...metadata
13268
13590
  };
13269
- if ("inputs" in node) {
13591
+ if (!isTriggerNode(node)) {
13270
13592
  const clean = { ...next };
13271
13593
  if (!Object.hasOwn(update, "timeoutMs")) delete clean.timeoutMs;
13272
13594
  if (!Object.hasOwn(update, "maxExecutions")) delete clean.maxExecutions;
13273
13595
  next = clean;
13274
13596
  } else if (update.timeoutMs != null || update.maxExecutions != null) fail("node.invalid-field", "Trigger nodes do not have execution limits.");
13597
+ if (node.kind == "start" || node.kind == "outputs") {
13598
+ replace(ref, next);
13599
+ const ports = fieldsToPorts(node.kind == "start" ? config.inputDefs : config.outputDefs, node.kind == "start" ? node.inputDefs : node.outputDefs).filter((port) => "handle" in port);
13600
+ const changes = node.kind == "start" ? updateStartInputDefs(content, ref, ports) : updateOutputsDefs(content, ref, ports);
13601
+ if (changes.length > 0) apply(changes);
13602
+ return;
13603
+ }
13275
13604
  function taskInputs(task, reserved = []) {
13276
13605
  if (node.kind != "task") throw new Error("Expected a task.");
13277
13606
  const fields = record(config.inputs);
@@ -13307,7 +13636,16 @@ async function compileAuthoring(base, request, host) {
13307
13636
  } else if (node.kind == "task" && "executor" in node.task) {
13308
13637
  const before = node.task;
13309
13638
  let task;
13310
- if (type == "connector") {
13639
+ if (type == "workflow") {
13640
+ task = before.executor.kind == "workflow" && before.executor.flowId == config.flowId ? {
13641
+ ...before,
13642
+ name: String(update.name)
13643
+ } : await resolveWorkflow(String(config.flowId), String(update.name));
13644
+ next = withWorkflowTask({
13645
+ ...node,
13646
+ ...metadata
13647
+ }, task);
13648
+ } else if (type == "connector") {
13311
13649
  if (before.executor.kind == "connector" && config.action == before.executor.action) {
13312
13650
  const { connectionId: _connectionId, ...executor } = before.executor;
13313
13651
  task = {
@@ -13547,6 +13885,18 @@ async function compileAuthoring(base, request, host) {
13547
13885
  for (const edit of parsed.edits) {
13548
13886
  try {
13549
13887
  switch (edit.op) {
13888
+ case "node.refresh": {
13889
+ const ref = resolve(edit.node);
13890
+ const node = nodeAt(content, ref);
13891
+ if (node.kind != "task" || !("executor" in node.task) || node.task.executor.kind != "workflow") fail("node.invalid-type", "Only workflow call nodes support refresh.");
13892
+ apply([{
13893
+ kind: "graph.node.replace",
13894
+ nodeId: ref,
13895
+ before: node,
13896
+ node: withWorkflowTask(node, await resolveWorkflow(node.task.executor.flowId, node.name ?? node.task.name, node.task))
13897
+ }]);
13898
+ break;
13899
+ }
13550
13900
  case "node.add": {
13551
13901
  if (Object.hasOwn(aliases, edit.as)) fail("node.alias-duplicate", `Duplicate alias ${edit.as}.`);
13552
13902
  const nodeId = host.id(`node:${edit.as}`), identity = {
@@ -13557,6 +13907,21 @@ async function compileAuthoring(base, request, host) {
13557
13907
  const config = edit.config ?? {};
13558
13908
  let changes;
13559
13909
  switch (edit.type) {
13910
+ case "workflow":
13911
+ changes = createManagedTask(identity, await resolveWorkflow(String(authoringConfigurations.workflow.parse(config).flowId), name));
13912
+ break;
13913
+ case "outputs":
13914
+ changes = [{
13915
+ kind: "graph.node.create",
13916
+ nodeId,
13917
+ node: {
13918
+ outputDefs: [],
13919
+ outputMappings: {},
13920
+ kind: "outputs",
13921
+ name
13922
+ }
13923
+ }];
13924
+ break;
13560
13925
  case "code":
13561
13926
  changes = createCodeTask(identity, name, void 0, {
13562
13927
  inputs: [],
@@ -13609,6 +13974,7 @@ async function compileAuthoring(base, request, host) {
13609
13974
  node: {
13610
13975
  kind: edit.type,
13611
13976
  name,
13977
+ ...edit.type == "start" ? { inputDefs: [] } : {},
13612
13978
  ...edit.type == "cron" ? { cronTimes: [{
13613
13979
  type: "every",
13614
13980
  unit: "hour",
@@ -13689,10 +14055,10 @@ async function compileAuthoring(base, request, host) {
13689
14055
  kind: "module.delete",
13690
14056
  moduleId
13691
14057
  }]);
13692
- const cleaned = cleanVariableBindings(base, operations);
14058
+ const cleaned = cleanVariableBindings(upgraded, operations);
13693
14059
  return {
13694
14060
  operations: cleaned,
13695
- content: cleaned.length == 0 ? base : applyFlowChanges(base, cleaned),
14061
+ content: cleaned.length == 0 ? upgraded : applyFlowChanges(upgraded, cleaned),
13696
14062
  nodes: aliases
13697
14063
  };
13698
14064
  }
@@ -13715,7 +14081,7 @@ function authoringDiagnostics(content, diagnostics) {
13715
14081
  code: diagnostic.code,
13716
14082
  message,
13717
14083
  nodes: affected.map(([id]) => id),
13718
- field: affected[0] == null ? "config" : authoringDiagnosticField(content, affected[0][1], parts),
14084
+ field: authoringDiagnosticField(affected[0]?.[1], parts),
13719
14085
  ...diagnostic.line ? {
13720
14086
  line: diagnostic.line,
13721
14087
  column: diagnostic.column
@@ -13797,7 +14163,7 @@ var eventSourceRevisionSchema = strictObject({
13797
14163
  //#endregion
13798
14164
  //#region src/control/common/authoringExamples.ts
13799
14165
  var descriptions = {
13800
- "manual": "A Manual start node.",
14166
+ "start": "A Start node with a required message parameter. Supply it through trigger.outputs.",
13801
14167
  "error": "A Flow Error node. Select upstream Flows, then publish and enable this Flow to listen for failures in their automatic runs.",
13802
14168
  "webhook": "A Webhook start node.",
13803
14169
  "cron": "An hourly scheduled start node.",
@@ -13805,7 +14171,7 @@ var descriptions = {
13805
14171
  "integration": "Telegram webhook integration by key; replace CONNECTION_ID with an active Telegram connection.",
13806
14172
  "decision": "AI Decision evaluates named questions against target and returns a complete answer object per output. Configure target before running.",
13807
14173
  "openapi": "A fixed JSON API operation. Replace the example document and URL before running.",
13808
- "connector": "A Connector Task and its node. Replace ACTION_ID, CONNECTION_ID and port definitions using connector_get / connector show.",
14174
+ "connector": "A Connector Task and its node. Replace ACTION_ID, CONNECTION_ID and port definitions using connector_get / connector show. Set connectionId to an empty string to defer account configuration; execution will require an account.",
13809
14175
  "code": "A JavaScript module and its node. Use Code for custom computation; use Connector Tasks for existing actions.",
13810
14176
  "condition": "A condition with true and false execution branches.",
13811
14177
  "value": "A fixed value node.",
@@ -13845,11 +14211,16 @@ function authoringExample(name) {
13845
14211
  } } } } } } } }
13846
14212
  }, "https://api.example.com/openapi.json", "/items", "get")));
13847
14213
  break;
13848
- case "manual":
13849
- operations = createBuiltinTrigger("start", {
13850
- kind: "manual",
14214
+ case "start":
14215
+ operations = [...createBuiltinTrigger("start", {
14216
+ inputDefs: [{
14217
+ handle: "message",
14218
+ jsonSchema: { type: "string" },
14219
+ nullable: false
14220
+ }],
14221
+ kind: "start",
13851
14222
  name: "Start"
13852
- });
14223
+ })];
13853
14224
  break;
13854
14225
  case "webhook":
13855
14226
  operations = createBuiltinTrigger("start", {
@@ -14109,6 +14480,10 @@ var schemas = {
14109
14480
  expectedRevisionId: id,
14110
14481
  version
14111
14482
  }),
14483
+ upgradeDraft: strictObject({
14484
+ expectedRevisionId: id,
14485
+ version
14486
+ }),
14112
14487
  setEnabled: strictObject({
14113
14488
  enabled: boolean(),
14114
14489
  expectedPublicationId: id,
@@ -14205,6 +14580,7 @@ var controlRequests = {
14205
14580
  };
14206
14581
  },
14207
14582
  repairDraft: decoder(schemas.repairDraft),
14583
+ upgradeDraft: decoder(schemas.upgradeDraft),
14208
14584
  setEnabled: decoder(schemas.setEnabled),
14209
14585
  updatePresentation: decoder(schemas.updatePresentation),
14210
14586
  checkFlow: decoder(schemas.checkFlow),
@@ -14233,4 +14609,4 @@ function controlRequestSchema(name) {
14233
14609
  return schema;
14234
14610
  }
14235
14611
  //#endregion
14236
- 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 };
14612
+ 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 };