@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
@@ -6597,6 +6597,7 @@ var webhookMethods = [
6597
6597
  "DELETE"
6598
6598
  ];
6599
6599
  var text = string();
6600
+ var actionConnection = text.describe("Account selection: omit while unconfigured; use an account ID to select it; use \"\" to explicitly defer configuration. Deferred Actions fail if called; deferred Agent tools are excluded from the callable tool set. Not supported by Triggers.");
6600
6601
  var json = json$1();
6601
6602
  var strings = array(text);
6602
6603
  var port = object({
@@ -6605,6 +6606,7 @@ var port = object({
6605
6606
  nullable: boolean(),
6606
6607
  handle: text
6607
6608
  });
6609
+ var workflowInputDefs = array(port.strict());
6608
6610
  var input = port.extend({ value: json.optional() });
6609
6611
  var group = object({
6610
6612
  collapsed: boolean().optional(),
@@ -6651,7 +6653,7 @@ var capability = union([
6651
6653
  mode: literal("independent"),
6652
6654
  actions: array(strictObject({
6653
6655
  action: text,
6654
- connectionId: text.optional()
6656
+ connectionId: actionConnection.optional()
6655
6657
  }))
6656
6658
  }),
6657
6659
  strictObject({
@@ -6711,7 +6713,7 @@ var managedFields = object({
6711
6713
  object({
6712
6714
  kind: literal("connector"),
6713
6715
  action: text,
6714
- connectionId: text.optional(),
6716
+ connectionId: actionConnection.optional(),
6715
6717
  outputMode: literal("value").optional()
6716
6718
  }),
6717
6719
  object({
@@ -6751,17 +6753,22 @@ var managedFields = object({
6751
6753
  name: text,
6752
6754
  description: text,
6753
6755
  action: text,
6754
- connectionId: text.optional(),
6756
+ connectionId: actionConnection.optional(),
6755
6757
  approval: boolean(),
6756
6758
  inputs: array(input.extend({ source: agentInput }))
6757
6759
  })),
6758
6760
  notification: object({
6759
6761
  action: text,
6760
- connectionId: text.optional(),
6762
+ connectionId: actionConnection.optional(),
6761
6763
  inputDefinitions: array(input),
6762
6764
  messageHandle: text,
6763
6765
  inputs: record$1(text, agentValue)
6764
6766
  }).optional()
6767
+ }),
6768
+ strictObject({
6769
+ kind: literal("workflow"),
6770
+ flowId: text,
6771
+ revisionId: text
6765
6772
  })
6766
6773
  ])
6767
6774
  });
@@ -6870,6 +6877,12 @@ var base = {
6870
6877
  timeoutMs: number().optional()
6871
6878
  };
6872
6879
  var node = union([
6880
+ strictObject({
6881
+ ...base,
6882
+ kind: literal("outputs"),
6883
+ outputDefs: array(port.strict()),
6884
+ outputMappings: inputs
6885
+ }).omit({ inputs: true }),
6873
6886
  object({
6874
6887
  ...base,
6875
6888
  inputs: record$1(text, never()),
@@ -6902,6 +6915,11 @@ var node = union([
6902
6915
  ...trigger,
6903
6916
  kind: literal("manual")
6904
6917
  }),
6918
+ strictObject({
6919
+ ...trigger,
6920
+ kind: literal("start"),
6921
+ inputDefs: workflowInputDefs
6922
+ }),
6905
6923
  strictObject({
6906
6924
  ...trigger,
6907
6925
  kind: literal("error"),
@@ -6966,7 +6984,7 @@ var module = object({
6966
6984
  imports: strings,
6967
6985
  source: text
6968
6986
  });
6969
- var document = preprocess(rejectRetiredDefinitions, object({
6987
+ var document = preprocess(normalizeDocument, object({
6970
6988
  bindings: record$1(text, binding),
6971
6989
  graph
6972
6990
  }));
@@ -6975,7 +6993,9 @@ object({
6975
6993
  literal(2),
6976
6994
  literal(4),
6977
6995
  literal(5),
6978
- literal(6)
6996
+ literal(6),
6997
+ literal(7),
6998
+ literal(8)
6979
6999
  ]),
6980
7000
  document,
6981
7001
  modules: record$1(text, module)
@@ -6983,13 +7003,19 @@ object({
6983
7003
  kind: literal("open-flow-flow-revision"),
6984
7004
  version: literal(1)
6985
7005
  });
6986
- function rejectRetiredDefinitions(value) {
7006
+ function normalizeDocument(value) {
6987
7007
  const candidate = record(value);
6988
7008
  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.");
6989
7009
  if (Object.values(record(record(candidate.graph).nodes)).some((candidateNode) => Object.hasOwn(record(candidateNode), "taskId"))) throw new TypeError("Task references are no longer supported.");
6990
7010
  const subflows = candidate.subflows;
6991
7011
  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.");
6992
7012
  if (Object.values(record(record(candidate.graph).nodes)).some((candidateNode) => record(candidateNode).kind === "subflow")) throw new TypeError("Subflow nodes are no longer supported.");
7013
+ if ([
7014
+ "inputDefs",
7015
+ "outputDefs",
7016
+ "outputMappings"
7017
+ ].some((field) => Object.hasOwn(candidate, field))) throw new TypeError("Workflow interface configuration must belong to Start and Outputs nodes.");
7018
+ if (Object.values(record(record(candidate.graph).nodes)).some((candidateNode) => record(candidateNode).kind == "start" && Object.hasOwn(record(candidateNode), "parameters"))) throw new TypeError("Legacy Start.parameters is unsupported; configure node.inputDefs.");
6993
7019
  return value;
6994
7020
  }
6995
7021
  function record(value) {
@@ -1,10 +1,12 @@
1
- import type { CodeModule, FlowDocument, Graph, Group, InputPort, JsonValue, ManagedTaskDefinition, Port, RevisionContent, TriggerNode } from '@oomol-lab/open-flow/flow-change';
1
+ import type { CodeModule, FlowDocument, Graph, Group, InputMapping, InputPort, JsonValue, ManagedTaskDefinition, Port, RevisionContent, TriggerNode } from '@oomol-lab/open-flow/flow-change';
2
2
  export * from './flow-workflowFile.js';
3
3
  export { maxJsonDepth } from './flow-json.js';
4
- export { decodeFlowDocument, decodeRevisionContent } from '../browser/flow-change-schema.js';
4
+ export { decodeFlowDocument, decodeRevisionContent, upgradeWorkflowInterfaceDocument } from '../browser/flow-change-schema.js';
5
+ export { upgradeRevisionContent } from '@oomol-lab/open-flow/flow-change';
5
6
  export declare function canonicalJsonBytes(value: JsonValue): Uint8Array;
6
7
  export declare function digestBytes(bytes: Uint8Array): Promise<string>;
7
8
  export declare function canonicalPorts(value: readonly (InputPort | Port | Group)[]): JsonValue;
9
+ export declare function canonicalInputs(value: Readonly<Record<string, InputMapping>>): JsonValue;
8
10
  export declare function canonicalGraph(value: Graph): JsonValue;
9
11
  export declare function canonicalRevisionGraph(content: RevisionContent, graph: Graph): JsonValue;
10
12
  export declare function canonicalTask(task: ManagedTaskDefinition): JsonValue;
@@ -8579,6 +8579,7 @@ var webhookMethods = [
8579
8579
  "DELETE"
8580
8580
  ];
8581
8581
  var text = string();
8582
+ var actionConnection = text.describe("Account selection: omit while unconfigured; use an account ID to select it; use \"\" to explicitly defer configuration. Deferred Actions fail if called; deferred Agent tools are excluded from the callable tool set. Not supported by Triggers.");
8582
8583
  var json = json$1();
8583
8584
  var strings = array(text);
8584
8585
  var port = object({
@@ -8587,6 +8588,7 @@ var port = object({
8587
8588
  nullable: boolean(),
8588
8589
  handle: text
8589
8590
  });
8591
+ var workflowInputDefs = array(port.strict());
8590
8592
  var input = port.extend({ value: json.optional() });
8591
8593
  var group = object({
8592
8594
  collapsed: boolean().optional(),
@@ -8633,7 +8635,7 @@ var capability = union([
8633
8635
  mode: literal("independent"),
8634
8636
  actions: array(strictObject({
8635
8637
  action: text,
8636
- connectionId: text.optional()
8638
+ connectionId: actionConnection.optional()
8637
8639
  }))
8638
8640
  }),
8639
8641
  strictObject({
@@ -8693,7 +8695,7 @@ var managedFields = object({
8693
8695
  object({
8694
8696
  kind: literal("connector"),
8695
8697
  action: text,
8696
- connectionId: text.optional(),
8698
+ connectionId: actionConnection.optional(),
8697
8699
  outputMode: literal("value").optional()
8698
8700
  }),
8699
8701
  object({
@@ -8733,17 +8735,22 @@ var managedFields = object({
8733
8735
  name: text,
8734
8736
  description: text,
8735
8737
  action: text,
8736
- connectionId: text.optional(),
8738
+ connectionId: actionConnection.optional(),
8737
8739
  approval: boolean(),
8738
8740
  inputs: array(input.extend({ source: agentInput }))
8739
8741
  })),
8740
8742
  notification: object({
8741
8743
  action: text,
8742
- connectionId: text.optional(),
8744
+ connectionId: actionConnection.optional(),
8743
8745
  inputDefinitions: array(input),
8744
8746
  messageHandle: text,
8745
8747
  inputs: record$1(text, agentValue)
8746
8748
  }).optional()
8749
+ }),
8750
+ strictObject({
8751
+ kind: literal("workflow"),
8752
+ flowId: text,
8753
+ revisionId: text
8747
8754
  })
8748
8755
  ])
8749
8756
  });
@@ -8852,6 +8859,12 @@ var base = {
8852
8859
  timeoutMs: number().optional()
8853
8860
  };
8854
8861
  var node = union([
8862
+ strictObject({
8863
+ ...base,
8864
+ kind: literal("outputs"),
8865
+ outputDefs: array(port.strict()),
8866
+ outputMappings: inputs
8867
+ }).omit({ inputs: true }),
8855
8868
  object({
8856
8869
  ...base,
8857
8870
  inputs: record$1(text, never()),
@@ -8884,6 +8897,11 @@ var node = union([
8884
8897
  ...trigger,
8885
8898
  kind: literal("manual")
8886
8899
  }),
8900
+ strictObject({
8901
+ ...trigger,
8902
+ kind: literal("start"),
8903
+ inputDefs: workflowInputDefs
8904
+ }),
8887
8905
  strictObject({
8888
8906
  ...trigger,
8889
8907
  kind: literal("error"),
@@ -8948,7 +8966,7 @@ var module = object({
8948
8966
  imports: strings,
8949
8967
  source: text
8950
8968
  });
8951
- var document = preprocess(rejectRetiredDefinitions, object({
8969
+ var document = preprocess(normalizeDocument, object({
8952
8970
  bindings: record$1(text, binding),
8953
8971
  graph
8954
8972
  }));
@@ -8957,7 +8975,9 @@ var revision = object({
8957
8975
  literal(2),
8958
8976
  literal(4),
8959
8977
  literal(5),
8960
- literal(6)
8978
+ literal(6),
8979
+ literal(7),
8980
+ literal(8)
8961
8981
  ]),
8962
8982
  document,
8963
8983
  modules: record$1(text, module)
@@ -8966,15 +8986,73 @@ var envelope$1 = revision.extend({
8966
8986
  kind: literal("open-flow-flow-revision"),
8967
8987
  version: literal(1)
8968
8988
  });
8969
- function rejectRetiredDefinitions(value) {
8989
+ function normalizeDocument(value) {
8970
8990
  const candidate = record(value);
8971
8991
  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.");
8972
8992
  if (Object.values(record(record(candidate.graph).nodes)).some((candidateNode) => Object.hasOwn(record(candidateNode), "taskId"))) throw new TypeError("Task references are no longer supported.");
8973
8993
  const subflows = candidate.subflows;
8974
8994
  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.");
8975
8995
  if (Object.values(record(record(candidate.graph).nodes)).some((candidateNode) => record(candidateNode).kind === "subflow")) throw new TypeError("Subflow nodes are no longer supported.");
8996
+ if ([
8997
+ "inputDefs",
8998
+ "outputDefs",
8999
+ "outputMappings"
9000
+ ].some((field) => Object.hasOwn(candidate, field))) throw new TypeError("Workflow interface configuration must belong to Start and Outputs nodes.");
9001
+ if (Object.values(record(record(candidate.graph).nodes)).some((candidateNode) => record(candidateNode).kind == "start" && Object.hasOwn(record(candidateNode), "parameters"))) throw new TypeError("Legacy Start.parameters is unsupported; configure node.inputDefs.");
8976
9002
  return value;
8977
9003
  }
9004
+ /** Explicit storage upgrade only. Normal reads and authoring still reject retired fields. */
9005
+ function upgradeWorkflowInterfaceDocument(value) {
9006
+ const candidate = record(value);
9007
+ const sourceGraph = record(candidate.graph);
9008
+ const sourceNodes = record(sourceGraph.nodes);
9009
+ if (!([
9010
+ "inputDefs",
9011
+ "outputDefs",
9012
+ "outputMappings"
9013
+ ].some((field) => Object.hasOwn(candidate, field)) || Object.values(sourceNodes).some((entry) => {
9014
+ const candidateNode = record(entry);
9015
+ return candidateNode.kind == "start" && (!Object.hasOwn(candidateNode, "inputDefs") || Object.hasOwn(candidateNode, "parameters")) || candidateNode.kind == "outputs" && (!Object.hasOwn(candidateNode, "outputDefs") || !Object.hasOwn(candidateNode, "outputMappings"));
9016
+ }))) return value;
9017
+ if (candidate.graph !== sourceGraph || sourceGraph.nodes !== sourceNodes) throw new TypeError("Cannot migrate an invalid workflow graph.");
9018
+ const starts = Object.values(sourceNodes).filter((entry) => record(entry).kind == "start");
9019
+ const outputs = Object.values(sourceNodes).filter((entry) => record(entry).kind == "outputs");
9020
+ if (starts.length > 1 || outputs.length > 1) throw new TypeError("Cannot migrate duplicate Start or Outputs nodes.");
9021
+ const { inputDefs, outputDefs, outputMappings, ...sourceDocument } = candidate;
9022
+ if (starts.length == 0 && inputDefs !== void 0 && workflowInputDefs.parse(inputDefs).length > 0) throw new TypeError("Cannot migrate inputDefs without a Start node.");
9023
+ if (outputs.length == 0 && (outputDefs !== void 0 && workflowInputDefs.parse(outputDefs).length > 0 || outputMappings !== void 0 && Object.keys(inputs.parse(outputMappings)).length > 0)) throw new TypeError("Cannot migrate output configuration without an Outputs node.");
9024
+ return {
9025
+ ...sourceDocument,
9026
+ graph: {
9027
+ ...sourceGraph,
9028
+ nodes: Object.fromEntries(Object.entries(sourceNodes).map(([id, nodeValue]) => {
9029
+ const candidateNode = record(nodeValue);
9030
+ if (candidateNode.kind == "start") {
9031
+ const { parameters, ...rest } = candidateNode;
9032
+ return [id, {
9033
+ ...rest,
9034
+ inputDefs: workflowInputDefs.parse(mergeInterfaceConfiguration([
9035
+ candidateNode.inputDefs,
9036
+ parameters,
9037
+ inputDefs
9038
+ ], []))
9039
+ }];
9040
+ }
9041
+ if (candidateNode.kind == "outputs") return [id, {
9042
+ ...candidateNode,
9043
+ outputDefs: workflowInputDefs.parse(mergeInterfaceConfiguration([candidateNode.outputDefs, outputDefs], [])),
9044
+ outputMappings: inputs.parse(mergeInterfaceConfiguration([candidateNode.outputMappings, outputMappings], {}))
9045
+ }];
9046
+ return [id, nodeValue];
9047
+ }))
9048
+ }
9049
+ };
9050
+ }
9051
+ function mergeInterfaceConfiguration(values, fallback) {
9052
+ const present = values.filter((value) => value !== void 0);
9053
+ if (present.some((value) => !dequal(value, present[0]))) throw new TypeError("Conflicting workflow interface configuration.");
9054
+ return present.length == 0 ? fallback : present[0];
9055
+ }
8978
9056
  function record(value) {
8979
9057
  return value != null && typeof value == "object" && !Array.isArray(value) ? value : {};
8980
9058
  }
@@ -9154,14 +9232,14 @@ function repairRevisionEnvelope(value) {
9154
9232
  checkJsonDepth(value);
9155
9233
  const envelopeSource = record(value);
9156
9234
  if (envelopeSource.kind != "open-flow-flow-revision" || envelopeSource.version != 1) throw new TypeError("The value is not an Open Flow Revision envelope.");
9157
- if (typeof envelopeSource.modelVersion == "number" && envelopeSource.modelVersion > 6) throw new TypeError("The Flow model is newer than this package.");
9235
+ if (typeof envelopeSource.modelVersion == "number" && envelopeSource.modelVersion > 8) throw new TypeError("The Flow model is newer than this package.");
9158
9236
  let sourceDocument = record(envelopeSource.modelVersion == 1 || envelopeSource.modelVersion == 2 ? upgradeLegacyDocument(envelopeSource.document) : envelopeSource.document);
9159
9237
  if (typeof envelopeSource.modelVersion == "number" && envelopeSource.modelVersion < 6) sourceDocument = upgradeTaskNodes(sourceDocument);
9160
- rejectRetiredDefinitions(sourceDocument);
9238
+ sourceDocument = record(normalizeDocument(sourceDocument));
9161
9239
  const bindings = record(sourceDocument.bindings);
9162
9240
  const sourceGraph = repairGraph(sourceDocument.graph, bindings);
9163
9241
  return decodeRevisionContent({
9164
- modelVersion: 6,
9242
+ modelVersion: 8,
9165
9243
  document: {
9166
9244
  bindings: repairedEntries(sourceDocument.bindings, binding),
9167
9245
  graph: sourceGraph
@@ -9349,6 +9427,8 @@ array(union([...new Map(Object.entries(shapes).map(([kind, shape]) => [kind, sha
9349
9427
  ...shape
9350
9428
  })])).values()])).min(1);
9351
9429
  function checkModelVersion(content) {
9430
+ 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.");
9431
+ 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.");
9352
9432
  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.");
9353
9433
  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.");
9354
9434
  }
@@ -9374,6 +9454,47 @@ function clearConditionBindings(node) {
9374
9454
  };
9375
9455
  }
9376
9456
  //#endregion
9457
+ //#region src/flow/common/change.ts
9458
+ function isTriggerNode(node) {
9459
+ return [
9460
+ "manual",
9461
+ "start",
9462
+ "error",
9463
+ "webhook",
9464
+ "cron",
9465
+ "poll",
9466
+ "integration"
9467
+ ].includes(node.kind);
9468
+ }
9469
+ /** Lossless upgrade of readable content. Historical content and its encoding stay unchanged. */
9470
+ function upgradeRevisionContent(content) {
9471
+ const upgraded = upgradeDecodedRevisionContent(decodeRevisionContent(content));
9472
+ return dequal(content, upgraded) ? content : upgraded;
9473
+ }
9474
+ function upgradeDecodedRevisionContent(content) {
9475
+ const graph = content.document.graph;
9476
+ const hasManual = Object.values(graph.nodes).some((node) => node.kind == "manual");
9477
+ if (!hasManual && content.modelVersion == 8) return content;
9478
+ return {
9479
+ ...content,
9480
+ modelVersion: 8,
9481
+ document: {
9482
+ ...content.document,
9483
+ graph: hasManual ? {
9484
+ ...graph,
9485
+ nodes: Object.fromEntries(Object.entries(graph.nodes).map(([id, node]) => [id, upgradeManualTrigger(node)]))
9486
+ } : graph
9487
+ }
9488
+ };
9489
+ }
9490
+ function upgradeManualTrigger(node) {
9491
+ return node.kind == "manual" ? {
9492
+ ...node,
9493
+ kind: "start",
9494
+ inputDefs: []
9495
+ } : node;
9496
+ }
9497
+ //#endregion
9377
9498
  //#region src/trigger/common/config.ts
9378
9499
  /** Deployment-bound selections owned by the Trigger configuration contract. */
9379
9500
  function clearTriggerExternalConfig(key, config) {
@@ -9402,6 +9523,7 @@ function clearNodeConnections(graph, connectionId) {
9402
9523
  if ("executor" in node.task) {
9403
9524
  const executor = node.task.executor;
9404
9525
  const clear = (value) => {
9526
+ if (value.connectionId === "") return value;
9405
9527
  if (connectionId != null && value.connectionId != connectionId) return value;
9406
9528
  const { connectionId: _, ...rest } = value;
9407
9529
  return rest;
@@ -9446,6 +9568,7 @@ function clearNodeConnections(graph, connectionId) {
9446
9568
  return {
9447
9569
  ...capability,
9448
9570
  actions: capability.actions.map((action) => {
9571
+ if (action.connectionId === "") return action;
9449
9572
  if (connectionId != null && action.connectionId != connectionId) return action;
9450
9573
  const { connectionId: _, ...remaining } = action;
9451
9574
  return remaining;
@@ -9502,6 +9625,10 @@ function cleanWorkflowFile(value) {
9502
9625
  ...node,
9503
9626
  inputs: Object.fromEntries(Object.entries(node.inputs).map(([key, input]) => [key, cleanInput(input)]))
9504
9627
  };
9628
+ if (node.kind == "outputs") node = {
9629
+ ...node,
9630
+ outputMappings: Object.fromEntries(Object.entries(node.outputMappings).map(([key, input]) => [key, cleanInput(input)]))
9631
+ };
9505
9632
  if (node.kind == "condition") node = clearConditionBindings(node);
9506
9633
  if (node.kind == "error" && node.sourceFlowIds != null) node = {
9507
9634
  ...node,
@@ -9606,16 +9733,22 @@ function canonicalOperand(operand) {
9606
9733
  };
9607
9734
  }
9608
9735
  function canonicalNode(value) {
9609
- if (!("inputs" in value)) return canonicalTriggerNode(value);
9736
+ if (isTriggerNode(value)) return canonicalTriggerNode(value);
9610
9737
  const common = {
9611
9738
  ...value.description == null ? {} : { description: value.description },
9612
9739
  ...value.icon == null ? {} : { icon: value.icon },
9613
- inputs: canonicalInputs(value.inputs),
9740
+ ...value.kind == "outputs" ? {} : { inputs: canonicalInputs(value.inputs) },
9614
9741
  ...value.name == null ? {} : { name: value.name },
9615
9742
  ...value.maxExecutions == null ? {} : { maxExecutions: value.maxExecutions },
9616
9743
  ...value.timeoutMs == null ? {} : { timeoutMs: value.timeoutMs }
9617
9744
  };
9618
9745
  switch (value.kind) {
9746
+ case "outputs": return {
9747
+ ...common,
9748
+ kind: value.kind,
9749
+ outputDefs: canonicalPorts(value.outputDefs),
9750
+ outputMappings: canonicalInputs(value.outputMappings)
9751
+ };
9619
9752
  case "condition": return {
9620
9753
  ...common,
9621
9754
  cases: value.cases.map((item) => ({
@@ -9795,6 +9928,10 @@ function canonicalTriggerNode(trigger) {
9795
9928
  ...trigger.sourceFlowIds == null ? {} : { sourceFlowIds: [...trigger.sourceFlowIds] }
9796
9929
  };
9797
9930
  case "manual": return common(trigger.kind);
9931
+ case "start": return {
9932
+ ...common(trigger.kind),
9933
+ inputDefs: canonicalPorts(trigger.inputDefs)
9934
+ };
9798
9935
  case "webhook": return {
9799
9936
  ...common(trigger.kind),
9800
9937
  bodyFields: trigger.bodyFields.map((input) => ({
@@ -9886,10 +10023,10 @@ function revisionRepairKind(bytes) {
9886
10023
  return;
9887
10024
  }
9888
10025
  const source = value;
9889
- return typeof source.modelVersion == "number" && source.modelVersion < 6 ? "upgrade" : "repair";
10026
+ return typeof source.modelVersion == "number" && source.modelVersion < 8 ? "upgrade" : "repair";
9890
10027
  }
9891
10028
  function repairRevision(bytes) {
9892
10029
  return repairRevisionEnvelope(revisionValue(bytes));
9893
10030
  }
9894
10031
  //#endregion
9895
- export { canonicalDocument, canonicalGraph, canonicalJsonBytes, canonicalModule, canonicalPorts, canonicalRevisionGraph, canonicalTask, cleanWorkflowFile, decodeFlowDocument, decodeRevision, decodeRevisionContent, decodeWorkflowFile, digestBytes, encodeRevision, encodeWorkflowFile, maxJsonDepth, parseWorkflowFile, repairRevision, revisionRepairKind, triggerRuntimeJson, workflowFileName, workflowNameFromFile };
10032
+ export { canonicalDocument, canonicalGraph, canonicalInputs, canonicalJsonBytes, canonicalModule, canonicalPorts, canonicalRevisionGraph, canonicalTask, cleanWorkflowFile, decodeFlowDocument, decodeRevision, decodeRevisionContent, decodeWorkflowFile, digestBytes, encodeRevision, encodeWorkflowFile, maxJsonDepth, parseWorkflowFile, repairRevision, revisionRepairKind, triggerRuntimeJson, upgradeRevisionContent, upgradeWorkflowInterfaceDocument, workflowFileName, workflowNameFromFile };
@@ -54,6 +54,6 @@ export declare function checkInputSource(graph: Graph, target: string, handle: s
54
54
  export declare function checkInputSources(graph: Graph, target: string, handle: string, sources: readonly Pick<NodeSource, 'nodeId' | 'output' | 'field'>[]): InputSourcesCheck;
55
55
  /** Enumerate structurally available outputs while retaining their compatibility with one input. */
56
56
  export declare function inputSourceCandidates(graph: Graph, target: string, handle: string): Readonly<Record<string, readonly InputSourceCandidate[]>>;
57
- export declare function availableOutputs(graph: Graph, target: string, handle?: string): Readonly<Record<string, readonly string[]>>;
57
+ export declare function availableOutputs(graph: Graph, target: string, handle: string | undefined): Readonly<Record<string, readonly string[]>>;
58
58
  export declare function validateFlowGraph(revision: RevisionContent): readonly Diagnostic[];
59
59
  export {};
@@ -1,9 +1,9 @@
1
1
  export { renderPrompt } from './flow-promptTemplate.js';
2
2
  export { connectionUsage, removeConnectionUsage } from './flow-connectionUsage.js';
3
- export { matchesTriggerOutputs, triggerOutputDefinitions, triggerOutputPorts } from './trigger-contract.js';
3
+ export { matchesTriggerOutputs, normalizeTriggerOutputs, triggerOutputDefinitions, triggerOutputPorts } from './trigger-contract.js';
4
4
  import type { EngineContract } from './engine-contract.js';
5
5
  import type { RuntimeProgram } from './runtime-contract.js';
6
- import type { ConnectorActionCapability, ConnectorCapability, Graph, RevisionContent, SchemaMismatch } from '../browser/flow-change.js';
6
+ import type { ConnectorActionCapability, ConnectorCapability, Graph, InputMapping, JsonValue, Port, RevisionContent, SchemaMismatch } from '../browser/flow-change.js';
7
7
  export { availableOutputs, graphOrder, nodeInputPorts } from './flow-graph.js';
8
8
  export { validateModules } from './flow-modules.js';
9
9
  export { matchesSchema, schemaValidationErrors, variableInputCompatible } from './flow-schema.js';
@@ -18,8 +18,11 @@ export interface SemanticClosure {
18
18
  }
19
19
  export declare function flowDependencies(content: RevisionContent, triggerId?: string): SemanticClosure['dependencies'];
20
20
  export declare function flowClosure(content: RevisionContent): Promise<SemanticClosure>;
21
+ /** Canonical semantic bytes, also used by transactional storage upgrades. */
22
+ export declare function encodeFlowClosure(content: RevisionContent, triggerId?: string): Uint8Array;
21
23
  export declare function variableBindings(revision: RevisionContent, bindingIds: Iterable<string>): Readonly<Record<string, string>>;
22
24
  export interface FlowResourceReferences {
25
+ readonly calledFlowIds?: readonly string[];
23
26
  readonly variableNames: readonly string[];
24
27
  readonly connections: readonly {
25
28
  readonly providerId: string;
@@ -45,9 +48,16 @@ export interface FlowValidation {
45
48
  }
46
49
  export type FlowInputsValidation = 'invalid' | 'valid';
47
50
  export declare function validRunTrigger(revision: RevisionContent, value: unknown): boolean;
51
+ export declare function normalizeRunTrigger(revision: RevisionContent, value: unknown): {
52
+ readonly nodeId: string;
53
+ readonly outputs: Readonly<Record<string, JsonValue>>;
54
+ } | undefined;
48
55
  export declare function validateFlowInputs(revision: RevisionContent, value: unknown): FlowInputsValidation;
49
56
  export declare function validateFlow(revision: RevisionContent, engine: EngineContract): Promise<FlowValidation>;
50
57
  export interface PreparedFlow {
58
+ readonly inputDefs: readonly Port[];
59
+ readonly outputDefs: readonly Port[];
60
+ readonly outputMappings: Readonly<Record<string, InputMapping>>;
51
61
  readonly closureDigest: string;
52
62
  readonly engineContract: string;
53
63
  readonly graph: Graph;