@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
@@ -22,6 +22,15 @@ function dequal(foo, bar) {
22
22
  return foo !== foo && bar !== bar;
23
23
  }
24
24
  //#endregion
25
+ //#region src/openapi/common/authBindings.ts
26
+ /** Never allow credentials to enter a Revision as literal node inputs. */
27
+ function assertOpenApiAuthBindings(document) {
28
+ for (const node of Object.values(document.graph.nodes)) {
29
+ if (node.kind != "task" || !("executor" in node.task) || node.task.executor.kind != "openapi") continue;
30
+ for (const [handle, mapping] of Object.entries(node.inputs)) if (handle.startsWith("auth.") && mapping.kind == "value") throw new TypeError("OpenAPI authentication accepts deployment variables and upstream outputs only.");
31
+ }
32
+ }
33
+ //#endregion
25
34
  //#region ../../node_modules/.bun/zod@4.6.5/node_modules/zod/v4/core/util.js
26
35
  function getEnumValues(entries) {
27
36
  const numericValues = Object.values(entries).filter((v) => typeof v === "number");
@@ -5691,50 +5700,6 @@ function preprocess(fn, schema) {
5691
5700
  });
5692
5701
  }
5693
5702
  //#endregion
5694
- //#region src/flow/common/webhookMethod.ts
5695
- var webhookMethods = [
5696
- "GET",
5697
- "POST",
5698
- "PUT",
5699
- "PATCH",
5700
- "DELETE"
5701
- ];
5702
- function webhookSupportsBody(method) {
5703
- return method !== "GET";
5704
- }
5705
- //#endregion
5706
- //#region src/openapi/common/authBindings.ts
5707
- /** Never allow credentials to enter a Revision as literal node inputs. */
5708
- function assertOpenApiAuthBindings(document) {
5709
- for (const node of Object.values(document.graph.nodes)) {
5710
- if (node.kind != "task" || !("executor" in node.task) || node.task.executor.kind != "openapi") continue;
5711
- for (const [handle, mapping] of Object.entries(node.inputs)) if (handle.startsWith("auth.") && mapping.kind == "value") throw new TypeError("OpenAPI authentication accepts deployment variables and upstream outputs only.");
5712
- }
5713
- }
5714
- //#endregion
5715
- //#region src/flow/common/change.ts
5716
- var schemaKeywords = /* @__PURE__ */ new Set([
5717
- "const",
5718
- "enum",
5719
- "exclusiveMaximum",
5720
- "exclusiveMinimum",
5721
- "maximum",
5722
- "maxItems",
5723
- "maxLength",
5724
- "maxProperties",
5725
- "minimum",
5726
- "minItems",
5727
- "minLength",
5728
- "minProperties",
5729
- "multipleOf",
5730
- "pattern",
5731
- "required",
5732
- "type"
5733
- ]);
5734
- function isSchemaKeyword(value) {
5735
- return schemaKeywords.has(value);
5736
- }
5737
- //#endregion
5738
5703
  //#region src/json-schema-subset/utils.ts
5739
5704
  var nextId = 0;
5740
5705
  function createId() {
@@ -8601,6 +8566,18 @@ var triggerScheduleSchema = array(union([object({
8601
8566
  ]),
8602
8567
  value: number()
8603
8568
  })]));
8569
+ //#endregion
8570
+ //#region src/flow/common/webhookMethod.ts
8571
+ var webhookMethods = [
8572
+ "GET",
8573
+ "POST",
8574
+ "PUT",
8575
+ "PATCH",
8576
+ "DELETE"
8577
+ ];
8578
+ function webhookSupportsBody(method) {
8579
+ return method !== "GET";
8580
+ }
8604
8581
  var text = string$1();
8605
8582
  var json$3 = json$4();
8606
8583
  var strings$1 = array(text);
@@ -8610,6 +8587,7 @@ var port$1 = object({
8610
8587
  nullable: boolean(),
8611
8588
  handle: text
8612
8589
  });
8590
+ var workflowInputDefs = array(port$1.strict());
8613
8591
  var input = port$1.extend({ value: json$3.optional() });
8614
8592
  var group = object({
8615
8593
  collapsed: boolean().optional(),
@@ -8767,6 +8745,11 @@ var managedFields = object({
8767
8745
  messageHandle: text,
8768
8746
  inputs: record$3(text, agentValue)
8769
8747
  }).optional()
8748
+ }),
8749
+ strictObject({
8750
+ kind: literal("workflow"),
8751
+ flowId: text,
8752
+ revisionId: text
8770
8753
  })
8771
8754
  ])
8772
8755
  });
@@ -8875,6 +8858,12 @@ var base = {
8875
8858
  timeoutMs: number().optional()
8876
8859
  };
8877
8860
  var node = union([
8861
+ strictObject({
8862
+ ...base,
8863
+ kind: literal("outputs"),
8864
+ outputDefs: array(port$1.strict()),
8865
+ outputMappings: inputs
8866
+ }).omit({ inputs: true }),
8878
8867
  object({
8879
8868
  ...base,
8880
8869
  inputs: record$3(text, never()),
@@ -8907,6 +8896,11 @@ var node = union([
8907
8896
  ...trigger,
8908
8897
  kind: literal("manual")
8909
8898
  }),
8899
+ strictObject({
8900
+ ...trigger,
8901
+ kind: literal("start"),
8902
+ inputDefs: workflowInputDefs
8903
+ }),
8910
8904
  strictObject({
8911
8905
  ...trigger,
8912
8906
  kind: literal("error"),
@@ -8986,7 +8980,7 @@ var module = object({
8986
8980
  imports: strings$1,
8987
8981
  source: text
8988
8982
  });
8989
- var document = preprocess(rejectRetiredDefinitions, object({
8983
+ var document = preprocess(normalizeDocument, object({
8990
8984
  bindings: record$3(text, binding$1),
8991
8985
  graph
8992
8986
  }));
@@ -8995,7 +8989,9 @@ var revision = object({
8995
8989
  literal(2),
8996
8990
  literal(4),
8997
8991
  literal(5),
8998
- literal(6)
8992
+ literal(6),
8993
+ literal(7),
8994
+ literal(8)
8999
8995
  ]),
9000
8996
  document,
9001
8997
  modules: record$3(text, module)
@@ -9004,13 +9000,19 @@ revision.extend({
9004
9000
  kind: literal("open-flow-flow-revision"),
9005
9001
  version: literal(1)
9006
9002
  });
9007
- function rejectRetiredDefinitions(value) {
9003
+ function normalizeDocument(value) {
9008
9004
  const candidate = record$2(value);
9009
9005
  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.");
9010
9006
  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.");
9011
9007
  const subflows = candidate.subflows;
9012
9008
  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.");
9013
9009
  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.");
9010
+ if ([
9011
+ "inputDefs",
9012
+ "outputDefs",
9013
+ "outputMappings"
9014
+ ].some((field) => Object.hasOwn(candidate, field))) throw new TypeError("Workflow interface configuration must belong to Start and Outputs nodes.");
9015
+ 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.");
9014
9016
  return value;
9015
9017
  }
9016
9018
  function record$2(value) {
@@ -9176,10 +9178,100 @@ array(union([...new Map(Object.entries(shapes).map(([kind, shape]) => [kind, sha
9176
9178
  ...shape
9177
9179
  })])).values()])).min(1);
9178
9180
  function checkModelVersion(content) {
9181
+ 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.");
9182
+ 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.");
9179
9183
  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.");
9180
9184
  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.");
9181
9185
  }
9182
9186
  //#endregion
9187
+ //#region src/flow/common/change.ts
9188
+ var schemaKeywords = /* @__PURE__ */ new Set([
9189
+ "const",
9190
+ "enum",
9191
+ "exclusiveMaximum",
9192
+ "exclusiveMinimum",
9193
+ "maximum",
9194
+ "maxItems",
9195
+ "maxLength",
9196
+ "maxProperties",
9197
+ "minimum",
9198
+ "minItems",
9199
+ "minLength",
9200
+ "minProperties",
9201
+ "multipleOf",
9202
+ "pattern",
9203
+ "required",
9204
+ "type"
9205
+ ]);
9206
+ function isSchemaKeyword(value) {
9207
+ return schemaKeywords.has(value);
9208
+ }
9209
+ /** Lossless upgrade of readable content. Historical content and its encoding stay unchanged. */
9210
+ function upgradeRevisionContent(content) {
9211
+ const upgraded = upgradeDecodedRevisionContent(decodeRevisionContent(content));
9212
+ return dequal(content, upgraded) ? content : upgraded;
9213
+ }
9214
+ function upgradeDecodedRevisionContent(content) {
9215
+ const graph = content.document.graph;
9216
+ const hasManual = Object.values(graph.nodes).some((node) => node.kind == "manual");
9217
+ if (!hasManual && content.modelVersion == 8) return content;
9218
+ return {
9219
+ ...content,
9220
+ modelVersion: 8,
9221
+ document: {
9222
+ ...content.document,
9223
+ graph: hasManual ? {
9224
+ ...graph,
9225
+ nodes: Object.fromEntries(Object.entries(graph.nodes).map(([id, node]) => [id, upgradeManualTrigger(node)]))
9226
+ } : graph
9227
+ }
9228
+ };
9229
+ }
9230
+ function upgradeManualTrigger(node) {
9231
+ return node.kind == "manual" ? {
9232
+ ...node,
9233
+ kind: "start",
9234
+ inputDefs: []
9235
+ } : node;
9236
+ }
9237
+ //#endregion
9238
+ //#region src/workflow/common/workflow.ts
9239
+ var portSchema = object({
9240
+ handle: string$1().min(1),
9241
+ jsonSchema: json$4(),
9242
+ nullable: boolean(),
9243
+ description: string$1().optional()
9244
+ });
9245
+ strictObject({
9246
+ inputs: array(portSchema).nullable(),
9247
+ outputs: array(portSchema).nullable()
9248
+ });
9249
+ var workflowContractSchema = object({
9250
+ version: literal(1),
9251
+ flowId: string$1().min(1),
9252
+ name: string$1(),
9253
+ revisionId: string$1().min(1),
9254
+ publicationId: string$1().min(1),
9255
+ inputs: array(portSchema),
9256
+ outputs: array(portSchema).nullable()
9257
+ });
9258
+ var workflowReferencesSchema = object({
9259
+ version: literal(1),
9260
+ direction: _enum(["incoming", "outgoing"]),
9261
+ total: int().nonnegative(),
9262
+ nextOffset: int().nonnegative().optional(),
9263
+ references: array(object({
9264
+ flowId: string$1(),
9265
+ name: string$1().nullable(),
9266
+ available: boolean(),
9267
+ draft: boolean(),
9268
+ live: object({
9269
+ publicationId: string$1(),
9270
+ enabled: boolean()
9271
+ }).nullable()
9272
+ }))
9273
+ });
9274
+ //#endregion
9183
9275
  //#region src/control/common/authoringLlm.ts
9184
9276
  var authoringLlmConfiguration = strictObject({
9185
9277
  mode: _enum(["chat", "json"]),
@@ -9212,7 +9304,9 @@ var id$1 = string$1().min(1);
9212
9304
  var json$2 = json$4();
9213
9305
  var patch = record$3(id$1, json$2);
9214
9306
  var type = _enum([
9215
- "manual",
9307
+ "start",
9308
+ "outputs",
9309
+ "workflow",
9216
9310
  "webhook",
9217
9311
  "cron",
9218
9312
  "error",
@@ -9284,6 +9378,12 @@ var field = strictObject({
9284
9378
  description: string$1().optional()
9285
9379
  });
9286
9380
  var inputFields = record$3(id$1, field.extend({ default: json$2.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.");
9381
+ var flowInputFields = record$3(id$1, field).describe("Workflow input definitions by name. Omitted schema accepts any JSON; omitted nullable is true. No defaults. Supply call values as trigger.outputs.");
9382
+ 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.");
9383
+ var flowInputFieldsView = record$3(id$1, field.extend({
9384
+ schema: json$2,
9385
+ nullable: boolean()
9386
+ }));
9287
9387
  var outputFields = record$3(id$1, field).describe("Code return fields by name. Omitted schema accepts any JSON; omitted nullable is true.");
9288
9388
  var expression = strictObject({
9289
9389
  left: operand,
@@ -9297,7 +9397,9 @@ var when = union([
9297
9397
  strictObject({ any: array(union([expression, all])) })
9298
9398
  ]);
9299
9399
  var authoringConfigurations = {
9300
- manual: strictObject({}),
9400
+ workflow: strictObject({ flowId: id$1 }),
9401
+ start: strictObject({ inputDefs: flowInputFields.default({}) }),
9402
+ outputs: strictObject({ outputDefs: flowOutputFields.default({}) }),
9301
9403
  error: strictObject({ sourceFlowIds: array(id$1).optional() }),
9302
9404
  webhook: authoringDefinitionSchemas.webhook.omit({ bodyFields: true }).extend({ body: inputFields }).strict(),
9303
9405
  cron: strictObject({ schedule: authoringDefinitionSchemas.schedule }),
@@ -9368,6 +9470,10 @@ var authoringEditSchema = discriminatedUnion("op", [
9368
9470
  set: updates.optional(),
9369
9471
  clear: array(array(id$1).min(1)).optional()
9370
9472
  }),
9473
+ strictObject({
9474
+ op: literal("node.refresh"),
9475
+ node: referenceSchema
9476
+ }),
9371
9477
  strictObject({
9372
9478
  op: literal("node.remove"),
9373
9479
  node: referenceSchema
@@ -9478,7 +9584,7 @@ var authoringSearchResponse = object({
9478
9584
  revision: id$1,
9479
9585
  data: object({
9480
9586
  matches: array(object({
9481
- node: id$1,
9587
+ node: id$1.optional(),
9482
9588
  field: id$1,
9483
9589
  line: int().optional(),
9484
9590
  excerpt: string$1()
@@ -9566,6 +9672,10 @@ function record$1(value) {
9566
9672
  function string(value) {
9567
9673
  return typeof value == "string" && value.length > 0 ? value : invalidResponse("Expected a non-empty string.");
9568
9674
  }
9675
+ function requiredFields(value, keys) {
9676
+ const missing = keys.filter((key) => !Object.hasOwn(value, key));
9677
+ if (missing.length > 0) invalidResponse(`Missing fields: ${missing.join(", ")}.`);
9678
+ }
9569
9679
  function exact(value, keys) {
9570
9680
  const actual = Object.keys(value);
9571
9681
  if (actual.length != keys.length || actual.some((key) => !keys.includes(key))) {
@@ -9633,7 +9743,7 @@ function publishOperation(value) {
9633
9743
  if (source.version != 1) return invalidResponse();
9634
9744
  switch (status) {
9635
9745
  case "pending":
9636
- exact(source, [
9746
+ requiredFields(source, [
9637
9747
  "createdAt",
9638
9748
  "flowId",
9639
9749
  "operationId",
@@ -9647,7 +9757,7 @@ function publishOperation(value) {
9647
9757
  status
9648
9758
  };
9649
9759
  case "succeeded":
9650
- exact(source, [
9760
+ requiredFields(source, [
9651
9761
  "createdAt",
9652
9762
  "flowId",
9653
9763
  "operationId",
@@ -9663,7 +9773,7 @@ function publishOperation(value) {
9663
9773
  status
9664
9774
  };
9665
9775
  case "failed": {
9666
- exact(source, [
9776
+ requiredFields(source, [
9667
9777
  "createdAt",
9668
9778
  "flowId",
9669
9779
  "issue",
@@ -9675,7 +9785,7 @@ function publishOperation(value) {
9675
9785
  ]);
9676
9786
  const issue = record$1(source.issue);
9677
9787
  const nodeId = issue.nodeId;
9678
- exact(issue, [
9788
+ requiredFields(issue, [
9679
9789
  "code",
9680
9790
  "message",
9681
9791
  ...nodeId == null ? [] : ["nodeId"]
@@ -9916,43 +10026,48 @@ var metadata = {
9916
10026
  var binding = unknown().transform(triggerBinding);
9917
10027
  var provider = {
9918
10028
  provider: string$1().min(1),
9919
- inputs: record$3(string$1(), discriminatedUnion("kind", [strictObject({
10029
+ inputs: record$3(string$1(), discriminatedUnion("kind", [object({
9920
10030
  kind: literal("value"),
9921
10031
  value: json$4()
9922
- }), strictObject({ kind: literal("unset") })]))
10032
+ }), object({ kind: literal("unset") })]))
9923
10033
  };
9924
10034
  var entrySchema = discriminatedUnion("type", [
9925
- strictObject({
10035
+ object({
10036
+ ...metadata,
10037
+ type: literal("start"),
10038
+ config: authoringConfigurations.start
10039
+ }),
10040
+ object({
9926
10041
  ...metadata,
9927
10042
  type: literal("manual"),
9928
- config: authoringConfigurations.manual
10043
+ config: object({})
9929
10044
  }),
9930
- strictObject({
10045
+ object({
9931
10046
  ...metadata,
9932
10047
  type: literal("webhook"),
9933
10048
  config: authoringConfigurations.webhook,
9934
10049
  binding
9935
10050
  }),
9936
- strictObject({
10051
+ object({
9937
10052
  ...metadata,
9938
10053
  type: literal("cron"),
9939
10054
  config: authoringConfigurations.cron,
9940
10055
  binding
9941
10056
  }),
9942
- strictObject({
10057
+ object({
9943
10058
  ...metadata,
9944
10059
  type: literal("error"),
9945
10060
  config: authoringConfigurations.error,
9946
10061
  binding
9947
10062
  }),
9948
- strictObject({
10063
+ object({
9949
10064
  ...metadata,
9950
10065
  ...provider,
9951
10066
  type: literal("poll"),
9952
10067
  config: authoringConfigurations.poll,
9953
10068
  binding
9954
10069
  }),
9955
- strictObject({
10070
+ object({
9956
10071
  ...metadata,
9957
10072
  ...provider,
9958
10073
  type: literal("integration"),
@@ -9965,9 +10080,10 @@ function decodeLiveDetails(value) {
9965
10080
  const flowId = string(source.flowId);
9966
10081
  if (source.version != 1 || !Array.isArray(source.entries)) return invalidResponse();
9967
10082
  if (source.publication === null) {
9968
- if (source.status != "not-published" || source.entries.length != 0 || Object.hasOwn(source, "enabled")) return invalidResponse();
10083
+ if (source.inputDefs !== null || source.status != "not-published" || source.entries.length != 0 || Object.hasOwn(source, "enabled")) return invalidResponse();
9969
10084
  return {
9970
10085
  flowId,
10086
+ inputDefs: null,
9971
10087
  publication: null,
9972
10088
  status: "not-published",
9973
10089
  entries: [],
@@ -9979,8 +10095,11 @@ function decodeLiveDetails(value) {
9979
10095
  if (current.flowId != flowId || typeof source.enabled != "boolean") return invalidResponse();
9980
10096
  if (status != "runnable" && status != "suspended") return invalidResponse();
9981
10097
  if (!source.enabled && source.status == "runnable") return invalidResponse();
10098
+ const inputDefs = flowInputFieldsView.safeParse(source.inputDefs);
10099
+ if (!inputDefs.success) return invalidResponse();
9982
10100
  return {
9983
10101
  flowId,
10102
+ inputDefs: inputDefs.data,
9984
10103
  publication: current,
9985
10104
  status,
9986
10105
  enabled: source.enabled,
@@ -9996,7 +10115,7 @@ function decodeEntries(values, current) {
9996
10115
  for (const entry of parsed.data) {
9997
10116
  if (ids.has(entry.nodeId)) return invalidResponse();
9998
10117
  ids.add(entry.nodeId);
9999
- if (entry.type != "manual" && (entry.binding.flowId != current.flowId || entry.binding.triggerNodeId != entry.nodeId || entry.binding.kind != entry.type || entry.binding.currentPublicationId != current.publicationId || entry.binding.currentRevisionId != current.revisionId)) return invalidResponse();
10118
+ if (entry.type != "start" && entry.type != "manual" && (entry.binding.flowId != current.flowId || entry.binding.triggerNodeId != entry.nodeId || entry.binding.kind != entry.type || entry.binding.currentPublicationId != current.publicationId || entry.binding.currentRevisionId != current.revisionId)) return invalidResponse();
10000
10119
  if (entry.type == "webhook" && (!entry.binding.endpointUrl || !webhookSupportsBody(entry.config.method) && Object.keys(entry.config.body).length > 0)) return invalidResponse();
10001
10120
  }
10002
10121
  return parsed.data;
@@ -10065,6 +10184,22 @@ function parseProviderAccessSource(value) {
10065
10184
  }
10066
10185
  //#endregion
10067
10186
  //#region src/control/common/connectorDecoders.ts
10187
+ function leinaBots(value) {
10188
+ const source = record$1(value);
10189
+ if (!Array.isArray(source.bots)) return invalidResponse("Leina bots: expected an array.");
10190
+ const bots = source.bots.map((entry) => {
10191
+ const bot = record$1(entry);
10192
+ if (!Array.isArray(bot.platforms)) return invalidResponse("Leina platforms: expected an array.");
10193
+ return {
10194
+ leinaId: string(bot.leinaId),
10195
+ name: string(bot.name),
10196
+ status: string(bot.status),
10197
+ platforms: bot.platforms.map(string)
10198
+ };
10199
+ });
10200
+ if (new Set(bots.map((bot) => bot.leinaId)).size != bots.length) return invalidResponse("Leina bots: duplicate identifiers.");
10201
+ return bots;
10202
+ }
10068
10203
  function accessPermissions(value) {
10069
10204
  const source = record$1(value);
10070
10205
  exact(source, [
@@ -10293,7 +10428,7 @@ function connectorAccessCandidatesBatch(value, providerIds) {
10293
10428
  }
10294
10429
  function connection(value) {
10295
10430
  const source = record$1(value);
10296
- exact(source, [
10431
+ requiredFields(source, [
10297
10432
  ...Object.hasOwn(source, "providerAccountId") ? ["providerAccountId"] : [],
10298
10433
  ...Object.hasOwn(source, "alias") ? ["alias"] : [],
10299
10434
  ...Object.hasOwn(source, "builtInAccount") ? ["builtInAccount"] : [],
@@ -10322,7 +10457,7 @@ function port(value, input = false) {
10322
10457
  const source = record$1(value);
10323
10458
  const description = source.description;
10324
10459
  const hasValue = input && Object.hasOwn(source, "value");
10325
- exact(source, [
10460
+ requiredFields(source, [
10326
10461
  "jsonSchema",
10327
10462
  "nullable",
10328
10463
  ...description == null ? [] : ["description"],
@@ -10347,7 +10482,7 @@ function connectorActionMetadata(value) {
10347
10482
  const source = record$1(value);
10348
10483
  const homepageUrl = source.homepageUrl;
10349
10484
  const icon = source.icon;
10350
- exact(source, [
10485
+ requiredFields(source, [
10351
10486
  "actionId",
10352
10487
  ...Object.hasOwn(source, "operationType") ? ["operationType"] : [],
10353
10488
  ...Object.hasOwn(source, "inputSchema") ? ["inputSchema"] : [],
@@ -10398,7 +10533,7 @@ function connectorProvider(value) {
10398
10533
  const homepageUrl = source.homepageUrl;
10399
10534
  const icon = source.icon;
10400
10535
  if (source.noSetup !== void 0 && typeof source.noSetup != "boolean") return invalidResponse();
10401
- exact(source, [
10536
+ requiredFields(source, [
10402
10537
  ...Object.hasOwn(source, "noSetup") ? ["noSetup"] : [],
10403
10538
  "serviceId",
10404
10539
  "serviceName",
@@ -10422,7 +10557,7 @@ function connectorProvider(value) {
10422
10557
  var id = string$1().min(1).max(256);
10423
10558
  var eventType = string$1().regex(/^[a-z][a-z0-9_.]{0,127}$/);
10424
10559
  var name = string$1().trim().min(1).max(128);
10425
- var eventSourceSchema = strictObject({
10560
+ var eventSourceSchema = object({
10426
10561
  version: literal(1),
10427
10562
  sourceId: id,
10428
10563
  revision: int().positive(),
@@ -10440,7 +10575,7 @@ var eventSourceSchema = strictObject({
10440
10575
  verifiedAt: string$1().nullable(),
10441
10576
  lastReceivedAt: string$1().nullable(),
10442
10577
  updatedAt: string$1(),
10443
- consumers: array(strictObject({
10578
+ consumers: array(object({
10444
10579
  flowId: id,
10445
10580
  flowName: string$1(),
10446
10581
  triggerNodeId: id
@@ -10450,7 +10585,7 @@ function decodeEventSource(value) {
10450
10585
  return eventSourceSchema.parse(value);
10451
10586
  }
10452
10587
  function decodeEventSources(value) {
10453
- return strictObject({
10588
+ return object({
10454
10589
  version: literal(1),
10455
10590
  sources: array(eventSourceSchema),
10456
10591
  teamId: id.nullable().optional()
@@ -10472,7 +10607,7 @@ function isUiLanguage(value) {
10472
10607
  //#region src/control/common/triggerCatalog.ts
10473
10608
  function decodeTriggerCatalog(value) {
10474
10609
  const source = record$1(value);
10475
- exact(source, [
10610
+ requiredFields(source, [
10476
10611
  "version",
10477
10612
  "locale",
10478
10613
  "definitions",
@@ -10486,7 +10621,7 @@ function decodeTriggerCatalog(value) {
10486
10621
  const display = Object.fromEntries(definitions.map((definition) => {
10487
10622
  const { key } = definition;
10488
10623
  const copy = record$1(entries[key]);
10489
- exact(copy, [
10624
+ requiredFields(copy, [
10490
10625
  "configInputs",
10491
10626
  "configInputLabels",
10492
10627
  "displayName",
@@ -10530,7 +10665,7 @@ strictObject({
10530
10665
  //#endregion
10531
10666
  //#region src/control/common/results.ts
10532
10667
  var json$1 = json$4();
10533
- var entry = strictObject({
10668
+ var entry = object({
10534
10669
  pointer: string$1(),
10535
10670
  type: _enum([
10536
10671
  "object",
@@ -10549,25 +10684,25 @@ var page = entry.extend({
10549
10684
  nextOffset: number().int().positive().optional(),
10550
10685
  entries: array(entry).optional()
10551
10686
  });
10552
- var result = strictObject({
10687
+ var result = object({
10553
10688
  resultId: string$1().min(1),
10554
10689
  callId: string$1().min(1),
10555
10690
  toolId: string$1().min(1),
10556
- source: discriminatedUnion("kind", [strictObject({
10691
+ source: discriminatedUnion("kind", [object({
10557
10692
  kind: literal("connector"),
10558
10693
  action: string$1().min(1)
10559
- }), strictObject({ kind: literal("code") })]),
10694
+ }), object({ kind: literal("code") })]),
10560
10695
  bytes: number().int().nonnegative(),
10561
10696
  digest: string$1().regex(/^[a-f0-9]{64}$/),
10562
10697
  createdAt: string$1().datetime()
10563
10698
  });
10564
- var listSchema = strictObject({
10699
+ var listSchema = object({
10565
10700
  version: literal(1),
10566
10701
  runId: string$1(),
10567
10702
  results: array(result),
10568
10703
  nextAfter: string$1().optional()
10569
10704
  });
10570
- var readSchema = strictObject({
10705
+ var readSchema = object({
10571
10706
  version: literal(1),
10572
10707
  runId: string$1(),
10573
10708
  result,
@@ -10644,7 +10779,7 @@ function connectorProvidersQuery(flowId, locale) {
10644
10779
  path: `/v1/connector/providers${parameters ? `?${parameters}` : ""}`,
10645
10780
  decode: (value) => {
10646
10781
  const source = record$1(value);
10647
- exact(source, ["providers", "version"]);
10782
+ requiredFields(source, ["providers", "version"]);
10648
10783
  if (source.version != 1 || !Array.isArray(source.providers)) return invalidResponse();
10649
10784
  return source.providers.map(connectorProvider);
10650
10785
  }
@@ -10659,7 +10794,7 @@ function connectorActionQuery(actionId, flowId, locale) {
10659
10794
  path: `/v1/connector/actions/${encodeURIComponent(actionId)}${parameters ? `?${parameters}` : ""}`,
10660
10795
  decode: (value) => {
10661
10796
  const source = record$1(value);
10662
- exact(source, ["action", "version"]);
10797
+ requiredFields(source, ["action", "version"]);
10663
10798
  if (source.version != 1) return invalidResponse();
10664
10799
  return connectorAction(source.action);
10665
10800
  }
@@ -10670,7 +10805,7 @@ function allConnectorConnectionsQuery(flowId) {
10670
10805
  path: `/v1/connector/connections${scope(flowId)}`,
10671
10806
  decode: (value) => {
10672
10807
  const source = record$1(value);
10673
- exact(source, ["connections", "version"]);
10808
+ requiredFields(source, ["connections", "version"]);
10674
10809
  if (source.version != 1 || !Array.isArray(source.connections)) return invalidResponse();
10675
10810
  return source.connections.map(connection);
10676
10811
  }
@@ -10681,7 +10816,7 @@ function connectorConnectionsQuery(serviceId, flowId) {
10681
10816
  path: `/v1/connector/connections/${encodeURIComponent(serviceId)}${scope(flowId)}`,
10682
10817
  decode: (value) => {
10683
10818
  const source = record$1(value);
10684
- exact(source, [
10819
+ requiredFields(source, [
10685
10820
  "connections",
10686
10821
  "serviceId",
10687
10822
  "version"
@@ -10706,6 +10841,7 @@ function resourceReferences(input) {
10706
10841
  if (accessRevision < 0) return invalidResponse();
10707
10842
  return {
10708
10843
  draft: draft == null ? null : {
10844
+ ...draft.calledFlowIds === void 0 ? {} : { calledFlowIds: strings(draft.calledFlowIds) },
10709
10845
  variableNames: strings(draft.variableNames),
10710
10846
  errorSourceFlowIds: strings(draft.errorSourceFlowIds),
10711
10847
  connections: draft.connections.map((value) => {
@@ -10736,10 +10872,11 @@ function flow(value) {
10736
10872
  if (source.version != 1) return invalidResponse();
10737
10873
  if (status != "active" && status != "retiring") return invalidResponse();
10738
10874
  const target = source.live == null ? void 0 : record$1(source.live);
10739
- if (target != null && typeof target.enabled != "boolean") return invalidResponse();
10875
+ if (target != null && (typeof target.enabled != "boolean" || typeof target.hasStart != "boolean")) return invalidResponse();
10740
10876
  return {
10741
10877
  ...target == null ? {} : { live: {
10742
10878
  enabled: target.enabled,
10879
+ hasStart: target.hasStart,
10743
10880
  publicationId: string(target.publicationId),
10744
10881
  revisionId: string(target.revisionId)
10745
10882
  } },
@@ -10770,7 +10907,7 @@ function flowPage(value) {
10770
10907
  }
10771
10908
  function variable(value) {
10772
10909
  const source = record$1(value);
10773
- exact(source, [
10910
+ requiredFields(source, [
10774
10911
  "name",
10775
10912
  "updatedAt",
10776
10913
  "value",
@@ -10790,6 +10927,15 @@ function variable(value) {
10790
10927
  version: 1
10791
10928
  };
10792
10929
  }
10930
+ function variableListItem(value) {
10931
+ const { referenceCount, ...fields } = record$1(value);
10932
+ const count = integer(referenceCount);
10933
+ if (count < 0) return invalidResponse();
10934
+ return {
10935
+ ...variable(fields),
10936
+ referenceCount: count
10937
+ };
10938
+ }
10793
10939
  function errorListener(value) {
10794
10940
  const source = record$1(value);
10795
10941
  if (typeof source.enabled != "boolean") return invalidResponse();
@@ -10803,17 +10949,13 @@ function errorListener(value) {
10803
10949
  }
10804
10950
  function variableReferences(input) {
10805
10951
  const source = record$1(input);
10806
- exact(source, [
10807
- "version",
10808
- "references",
10809
- "unknown"
10810
- ]);
10811
- if (source.version != 1 || !Array.isArray(source.references) || !Array.isArray(source.unknown)) return invalidResponse();
10952
+ requiredFields(source, ["version", "references"]);
10953
+ if (source.version != 1 || !Array.isArray(source.references)) return invalidResponse();
10812
10954
  return {
10813
10955
  version: 1,
10814
10956
  references: source.references.map((value) => {
10815
10957
  const item = record$1(value);
10816
- exact(item, [
10958
+ requiredFields(item, [
10817
10959
  "flowId",
10818
10960
  "flowName",
10819
10961
  "draft",
@@ -10822,7 +10964,7 @@ function variableReferences(input) {
10822
10964
  if (typeof item.draft != "boolean") return invalidResponse();
10823
10965
  const live = item.live === null ? null : record$1(item.live);
10824
10966
  if (live != null) {
10825
- exact(live, ["publicationId", "enabled"]);
10967
+ requiredFields(live, ["publicationId", "enabled"]);
10826
10968
  if (typeof live.enabled != "boolean") return invalidResponse();
10827
10969
  }
10828
10970
  return {
@@ -10834,20 +10976,6 @@ function variableReferences(input) {
10834
10976
  enabled: live.enabled
10835
10977
  }
10836
10978
  };
10837
- }),
10838
- unknown: source.unknown.map((value) => {
10839
- const item = record$1(value);
10840
- exact(item, [
10841
- "flowId",
10842
- "flowName",
10843
- "scope"
10844
- ]);
10845
- if (item.scope !== "draft" && item.scope !== "live") return invalidResponse();
10846
- return {
10847
- flowId: string(item.flowId),
10848
- flowName: string(item.flowName),
10849
- scope: item.scope
10850
- };
10851
10979
  })
10852
10980
  };
10853
10981
  }
@@ -10945,7 +11073,7 @@ function run(value) {
10945
11073
  }
10946
11074
  function runWaiting(value) {
10947
11075
  const source = record$1(value);
10948
- exact(source, [
11076
+ requiredFields(source, [
10949
11077
  "actions",
10950
11078
  "expiresAt",
10951
11079
  "nodeId",
@@ -10964,6 +11092,15 @@ function runWaiting(value) {
10964
11092
  waitingSince: string(source.waitingSince)
10965
11093
  };
10966
11094
  }
11095
+ function workflowIdentity(value) {
11096
+ const ref = record$1(value);
11097
+ return {
11098
+ flowId: string(ref.flowId),
11099
+ runId: string(ref.runId),
11100
+ nodeId: string(ref.nodeId),
11101
+ executionId: string(ref.executionId)
11102
+ };
11103
+ }
10967
11104
  function runDetails(value) {
10968
11105
  const source = record$1(value);
10969
11106
  const summary = run(source);
@@ -10971,20 +11108,24 @@ function runDetails(value) {
10971
11108
  if (eventsExpiresAt != null && typeof eventsExpiresAt != "string") return invalidResponse();
10972
11109
  if (source.waiting !== void 0 || !Array.isArray(source.waits)) return invalidResponse();
10973
11110
  const waits = source.waits.map(runWaiting);
10974
- if (new Set(waits.map((wait) => wait.waitId)).size != waits.length || summary.status == "waiting" && waits.length == 0 || [
11111
+ if (new Set(waits.map((wait) => wait.waitId)).size != waits.length || summary.status == "waiting" && waits.length == 0 && (!Array.isArray(source.calls) || source.calls.length == 0) || [
10975
11112
  "completed",
10976
11113
  "failed",
10977
11114
  "canceled",
10978
11115
  "indeterminate"
10979
11116
  ].includes(summary.status) && waits.length > 0) return invalidResponse();
10980
- if (source.occurrenceId === void 0 != (source.triggerNodeId === void 0)) return invalidResponse();
11117
+ if (source.occurrenceId !== void 0 && source.triggerNodeId === void 0) return invalidResponse();
10981
11118
  const state = {
10982
11119
  status: summary.status,
10983
11120
  waits
10984
11121
  };
11122
+ if (source.calls !== void 0 && !Array.isArray(source.calls)) return invalidResponse();
10985
11123
  const details = {
10986
11124
  ...summary,
10987
11125
  ...errorHandling(source),
11126
+ ...source.triggerNodeId === void 0 ? {} : { triggerNodeId: string(source.triggerNodeId) },
11127
+ ...source.caller === void 0 ? {} : { caller: workflowIdentity(source.caller) },
11128
+ ...source.calls === void 0 ? {} : { calls: source.calls.map((item) => Object.assign(workflowIdentity(item), { status: record$1(item).status === null ? null : runStatus(record$1(item).status) })) },
10988
11129
  closureDigest: string(source.closureDigest),
10989
11130
  engineContract: string(source.engineContract),
10990
11131
  engineDigest: string(source.engineDigest),
@@ -11035,7 +11176,7 @@ function runCancellation(value) {
11035
11176
  }
11036
11177
  function waitResolution(value) {
11037
11178
  const source = record$1(value);
11038
- exact(source, [
11179
+ requiredFields(source, [
11039
11180
  "action",
11040
11181
  "comment",
11041
11182
  "resolutionAccepted",
@@ -11252,7 +11393,7 @@ function decodeRunEvent(value) {
11252
11393
  switch (kind) {
11253
11394
  case "node.started": {
11254
11395
  const nodeKind = payload.nodeKind;
11255
- if (nodeKind !== void 0 && nodeKind !== "approval" && nodeKind !== "condition" && nodeKind !== "connector" && nodeKind !== "javascript" && nodeKind !== "decision" && nodeKind !== "openapi" && nodeKind !== "llm" && nodeKind !== "agent" && nodeKind !== "value" && nodeKind !== "wait") return invalidResponse();
11396
+ if (nodeKind !== void 0 && nodeKind !== "approval" && nodeKind !== "condition" && nodeKind !== "connector" && nodeKind !== "javascript" && nodeKind !== "decision" && nodeKind !== "openapi" && nodeKind !== "llm" && nodeKind !== "agent" && nodeKind !== "value" && nodeKind !== "outputs" && nodeKind !== "workflow" && nodeKind !== "wait") return invalidResponse();
11256
11397
  return {
11257
11398
  ...base,
11258
11399
  kind,
@@ -11379,14 +11520,14 @@ var ControlClient = class {
11379
11520
  if (options.limit != null) parameters.set("limit", String(options.limit));
11380
11521
  if (options.includeTotal != null) parameters.set("includeTotal", String(options.includeTotal));
11381
11522
  const query = parameters.size == 0 ? "" : `?${parameters}`;
11382
- return flowPage(await this.request(`/v1/flows${query}`));
11523
+ return flowPage(await this.request(`/v1/flows${query}`, options.signal == null ? void 0 : { signal: options.signal }));
11383
11524
  }
11384
11525
  async listEventSources(flowId, signal) {
11385
11526
  return decodeEventSources(await this.request("/v1/event-sources" + (flowId == null ? "" : `?flowId=${segment(flowId)}`), { signal }));
11386
11527
  }
11387
11528
  async listEventSourceConnections(teamId, signal) {
11388
11529
  const source = record$1(await this.request(`/v1/event-sources/connections${teamId == null ? "" : `?teamId=${segment(teamId)}`}`, { signal }));
11389
- exact(source, ["version", "connections"]);
11530
+ requiredFields(source, ["version", "connections"]);
11390
11531
  if (source.version != 1 || !Array.isArray(source.connections)) return invalidResponse();
11391
11532
  return source.connections.map(connection);
11392
11533
  }
@@ -11413,13 +11554,24 @@ var ControlClient = class {
11413
11554
  }
11414
11555
  async listVariables() {
11415
11556
  const source = record$1(await this.request("/v1/variables"));
11416
- exact(source, ["variables", "version"]);
11557
+ requiredFields(source, ["variables", "version"]);
11417
11558
  if (source.version != 1 || !Array.isArray(source.variables)) return invalidResponse();
11418
11559
  return {
11419
- variables: source.variables.map(variable),
11560
+ variables: source.variables.map(variableListItem),
11420
11561
  version: 1
11421
11562
  };
11422
11563
  }
11564
+ async getFlowReferences(flowId, options = {}) {
11565
+ const query = new URLSearchParams({
11566
+ direction: options.direction ?? "incoming",
11567
+ offset: String(options.offset ?? 0),
11568
+ limit: String(options.limit ?? 50)
11569
+ });
11570
+ return workflowReferencesSchema.parse(await this.request(`/v1/flows/${segment(flowId)}/references?${query}`, { signal: options.signal }));
11571
+ }
11572
+ async getWorkflowContract(flowId, signal) {
11573
+ return workflowContractSchema.parse(await this.request(`/v1/flows/${segment(flowId)}/call-contract`, { signal }));
11574
+ }
11423
11575
  async getVariableReferences(name, signal) {
11424
11576
  return variableReferences(await this.request(`/v1/variables/${segment(name)}/references`, { signal }));
11425
11577
  }
@@ -11434,7 +11586,7 @@ var ControlClient = class {
11434
11586
  }
11435
11587
  async deleteVariable(name) {
11436
11588
  const source = record$1(await this.request(`/v1/variables/${segment(name)}`, { method: "DELETE" }));
11437
- exact(source, ["version"]);
11589
+ requiredFields(source, ["version"]);
11438
11590
  if (source.version != 1) return invalidResponse();
11439
11591
  }
11440
11592
  async exportFlow(flowId) {
@@ -11476,7 +11628,7 @@ var ControlClient = class {
11476
11628
  command
11477
11629
  })
11478
11630
  }));
11479
- exact(source, [
11631
+ requiredFields(source, [
11480
11632
  "version",
11481
11633
  "flowId",
11482
11634
  "broadcast"
@@ -11616,11 +11768,11 @@ var ControlClient = class {
11616
11768
  }
11617
11769
  async listTriggerConfigOptions(flowId, nodeId, field, signal) {
11618
11770
  const source = record$1(await this.request(`/v1/flows/${segment(flowId)}/triggers/${segment(nodeId)}/options/${segment(field)}`, { signal }));
11619
- exact(source, ["options", "version"]);
11771
+ requiredFields(source, ["options", "version"]);
11620
11772
  if (source.version != 1 || !Array.isArray(source.options) || source.options.length > 1e3) return invalidResponse();
11621
11773
  return source.options.map((value) => {
11622
11774
  const item = record$1(value);
11623
- exact(item, [
11775
+ requiredFields(item, [
11624
11776
  "value",
11625
11777
  "label",
11626
11778
  ...item.color == null ? [] : ["color"]
@@ -11639,7 +11791,7 @@ var ControlClient = class {
11639
11791
  }
11640
11792
  async listConnectorTeams(signal) {
11641
11793
  const source = record$1(await this.request("/v1/connector/teams", { signal }));
11642
- exact(source, [
11794
+ requiredFields(source, [
11643
11795
  "enabled",
11644
11796
  "teams",
11645
11797
  "version"
@@ -11649,7 +11801,7 @@ var ControlClient = class {
11649
11801
  enabled: source.enabled,
11650
11802
  teams: source.teams.map((value) => {
11651
11803
  const team = record$1(value);
11652
- exact(team, [
11804
+ requiredFields(team, [
11653
11805
  "id",
11654
11806
  "name",
11655
11807
  "systemCreated"
@@ -11668,6 +11820,9 @@ var ControlClient = class {
11668
11820
  const query = connectorProvidersQuery(flowId, locale);
11669
11821
  return this.connectorRequest(query.path, "providers", signal, query.decode);
11670
11822
  }
11823
+ async listLeinaBots(flowId, signal) {
11824
+ return leinaBots(await this.request(`/v1/connector/leina/bots?flowId=${segment(flowId)}`, { signal }));
11825
+ }
11671
11826
  async removeConnectionUsage(flowId, connectionId, expectedRevisionId, expectedAccessRevision, idempotencyKey) {
11672
11827
  return draftChange(await this.request(`/v1/flows/${segment(flowId)}/connection-usage/remove`, {
11673
11828
  method: "POST",
@@ -11759,7 +11914,7 @@ var ControlClient = class {
11759
11914
  body: JSON.stringify({ version: 1 }),
11760
11915
  method: "POST"
11761
11916
  }));
11762
- exact(source, ["url", "version"]);
11917
+ requiredFields(source, ["url", "version"]);
11763
11918
  if (source.version != 1) return invalidResponse();
11764
11919
  try {
11765
11920
  const url = new URL(string(source.url));
@@ -11821,6 +11976,16 @@ var ControlClient = class {
11821
11976
  method: "POST"
11822
11977
  }));
11823
11978
  }
11979
+ async upgradeDraft(flowId, expectedRevisionId, options = {}) {
11980
+ return draftChange(await this.request(`/v1/flows/${segment(flowId)}/draft/upgrade`, {
11981
+ body: JSON.stringify({
11982
+ expectedRevisionId,
11983
+ version: 1
11984
+ }),
11985
+ headers: { "idempotency-key": options.idempotencyKey ?? operationKey("upgrade") },
11986
+ method: "POST"
11987
+ }));
11988
+ }
11824
11989
  async checkFlow(flowId, revisionId) {
11825
11990
  return flowCheck(await this.request(`/v1/flows/${segment(flowId)}/revisions/${segment(revisionId)}/check`, {
11826
11991
  body: JSON.stringify({
@@ -11963,7 +12128,7 @@ var ControlClient = class {
11963
12128
  const suffix = query == "" ? "" : `?${query}`;
11964
12129
  return this.connectorRequest(`/v1/connector/actions${suffix}`, "actions", signal, (value) => {
11965
12130
  const source = record$1(value);
11966
- exact(source, ["actions", "version"]);
12131
+ requiredFields(source, ["actions", "version"]);
11967
12132
  if (source.version != 1 || !Array.isArray(source.actions)) return invalidResponse();
11968
12133
  return source.actions.map(connectorAction);
11969
12134
  });
@@ -12100,15 +12265,16 @@ function addValueNode(harness, flowId, revisionId, nodeId = "marker", changeId)
12100
12265
  nodeId
12101
12266
  }], changeId);
12102
12267
  }
12103
- async function addManualTrigger(harness, flowId, revisionId) {
12268
+ async function addStartTrigger(harness, flowId, revisionId) {
12104
12269
  return changedRevisionId(await json(await changeRequest(harness, flowId, revisionId, [{
12105
12270
  kind: "graph.node.create",
12106
12271
  node: {
12107
- kind: "manual",
12272
+ inputDefs: [],
12273
+ kind: "start",
12108
12274
  name: "Start"
12109
12275
  },
12110
12276
  nodeId: "start"
12111
- }]), 200, "Add manual trigger"), "Manual trigger Revision");
12277
+ }]), 200, "Add Start node"), "Start Revision");
12112
12278
  }
12113
12279
  function changedRevisionId(change, message) {
12114
12280
  return requiredString(record(change.revision, `${message} revision`).revisionId, `${message} revisionId`);
@@ -12197,7 +12363,10 @@ var controlApiConformanceCases = [
12197
12363
  const idempotencyKey = crypto.randomUUID();
12198
12364
  const created = await api.importFlow(file, { idempotencyKey });
12199
12365
  equal(dequal(await api.importFlow(file, { idempotencyKey }), created), true, "Import retry must return the same Flow.");
12200
- equal(dequal(await api.exportFlow(created.flowId), file), true, "Export must retain the graph and Presentation.");
12366
+ equal(dequal(await api.exportFlow(created.flowId), {
12367
+ ...file,
12368
+ content: upgradeRevisionContent(file.content)
12369
+ }), true, "Export must upgrade legacy Manual nodes and retain the graph and Presentation.");
12201
12370
  const editor = await api.getEditor(created.flowId);
12202
12371
  equal(editor.live.publication == null, true, "Import must not publish.");
12203
12372
  equal(editor.draft.parentRevisionId == null, true, "Import must create an initial Revision.");
@@ -12304,12 +12473,107 @@ var controlApiConformanceCases = [
12304
12473
  equal((await api.checkAuthoring(flow.flowId, changed.revision)).revisionId, changed.revision, "Fixed check identity");
12305
12474
  }
12306
12475
  },
12476
+ {
12477
+ name: "authors Start parameters and admits their shared call contract",
12478
+ async verify(harness) {
12479
+ const api = client(harness), flow = await api.createFlow("Start parameters");
12480
+ equal((await api.authoringSchema(flow.flowId, { type: "start" })).type, "start", "Start discovery");
12481
+ const created = await api.editAuthoring(flow.flowId, {
12482
+ baseRevision: flow.draftRevisionId,
12483
+ requestId: "start-parameters-create",
12484
+ edits: [{
12485
+ op: "node.add",
12486
+ as: "start",
12487
+ type: "start",
12488
+ name: "Start",
12489
+ config: { inputDefs: {
12490
+ message: {
12491
+ schema: { type: "string" },
12492
+ nullable: false,
12493
+ description: "Original"
12494
+ },
12495
+ note: {
12496
+ schema: { type: "string" },
12497
+ nullable: true
12498
+ }
12499
+ } }
12500
+ }]
12501
+ });
12502
+ const nodeId = created.nodes.start;
12503
+ const changed = await api.editAuthoring(flow.flowId, {
12504
+ baseRevision: created.revision,
12505
+ requestId: "start-parameters-update",
12506
+ edits: [{
12507
+ op: "node.update",
12508
+ node: nodeId,
12509
+ set: { config: { inputDefs: { message: { description: "Call message" } } } }
12510
+ }]
12511
+ });
12512
+ equal(((await api.readAuthoring(flow.flowId, { nodes: [nodeId] })).data.nodes?.[0]?.config)?.inputDefs, {
12513
+ message: {
12514
+ schema: { type: "string" },
12515
+ nullable: false,
12516
+ description: "Call message"
12517
+ },
12518
+ note: {
12519
+ schema: { type: "string" },
12520
+ nullable: true
12521
+ }
12522
+ }, "Local parameter update preserves the contract");
12523
+ const runPath = `/v1/flows/${flow.flowId}/revisions/${changed.revision}/runs`;
12524
+ const run = (outputs, key) => request(harness, runPath, {
12525
+ method: "POST",
12526
+ headers: { "idempotency-key": key },
12527
+ body: JSON.stringify({
12528
+ engineContract,
12529
+ inputs: {},
12530
+ trigger: {
12531
+ nodeId,
12532
+ outputs
12533
+ },
12534
+ version: 2
12535
+ })
12536
+ });
12537
+ for (const [index, outputs] of [
12538
+ {},
12539
+ { message: 0 },
12540
+ {
12541
+ message: "Hello",
12542
+ extra: true
12543
+ }
12544
+ ].entries()) await error(await run(outputs, `start-invalid-${index}`), 400, "run.invalid", "Reject invalid Start parameters");
12545
+ const admitted = await json(await run({ message: "Hello" }, "start-call"), 202, "Admit omitted nullable parameter");
12546
+ equal(await json(await run({ message: "Hello" }, "start-call"), 200, "Replay Start call"), admitted, "Stable Start admission");
12547
+ await error(await run({
12548
+ message: "Hello",
12549
+ note: null
12550
+ }, "start-call"), 409, "run.conflict", "Preserve original request identity before normalization");
12551
+ await json(await run({
12552
+ message: "Hello",
12553
+ note: null
12554
+ }, "start-explicit-null"), 202, "Admit explicit null");
12555
+ equal(((await api.readAuthoring(flow.flowId, {
12556
+ revision: created.revision,
12557
+ nodes: [nodeId]
12558
+ })).data.nodes?.[0]?.config)?.inputDefs, {
12559
+ message: {
12560
+ schema: { type: "string" },
12561
+ nullable: false,
12562
+ description: "Original"
12563
+ },
12564
+ note: {
12565
+ schema: { type: "string" },
12566
+ nullable: true
12567
+ }
12568
+ }, "Fixed Start read preserves old configuration");
12569
+ }
12570
+ },
12307
12571
  {
12308
12572
  name: "admits simultaneous retries as one Run and preserves its Trigger identity",
12309
12573
  async verify(harness) {
12310
12574
  const flow = await createFlow(harness, "Concurrent Run", "concurrent-run-flow");
12311
12575
  const flowId = requiredString(flow.flowId, "Flow ID");
12312
- const revisionId = await addManualTrigger(harness, flowId, requiredString(flow.draftRevisionId, "Revision ID"));
12576
+ const revisionId = await addStartTrigger(harness, flowId, requiredString(flow.draftRevisionId, "Revision ID"));
12313
12577
  const submit = (payload = {}) => request(harness, `/v1/flows/${flowId}/revisions/${revisionId}/runs`, {
12314
12578
  method: "POST",
12315
12579
  headers: { "idempotency-key": "concurrent-run" },
@@ -12439,6 +12703,7 @@ var controlApiConformanceCases = [
12439
12703
  equal(created.name, "Control flow", "Created Flow name");
12440
12704
  equal(created.status, "active", "Created Flow status");
12441
12705
  equal(record(created.resourceReferences, "Flow resource references").draft, {
12706
+ calledFlowIds: [],
12442
12707
  variableNames: [],
12443
12708
  connections: [],
12444
12709
  errorSourceFlowIds: []
@@ -12610,7 +12875,7 @@ var controlApiConformanceCases = [
12610
12875
  async verify(harness) {
12611
12876
  const flow = await createFlow(harness, "Partial Draft", "partial-draft");
12612
12877
  const flowId = requiredString(flow.flowId, "Partial Flow identity");
12613
- const revisionId = changedRevisionId(await json(await changeRequest(harness, flowId, await addManualTrigger(harness, flowId, requiredString(flow.draftRevisionId, "Partial Draft identity")), [
12878
+ const revisionId = changedRevisionId(await json(await changeRequest(harness, flowId, await addStartTrigger(harness, flowId, requiredString(flow.draftRevisionId, "Partial Draft identity")), [
12614
12879
  {
12615
12880
  kind: "graph.node.create",
12616
12881
  nodeId: "other",
@@ -12680,7 +12945,7 @@ var controlApiConformanceCases = [
12680
12945
  async verify(harness) {
12681
12946
  const flow = await createFlow(harness, "Run flow", "run-flow");
12682
12947
  const flowId = requiredString(flow.flowId, "Run Flow flowId");
12683
- const draftRevisionId = await addManualTrigger(harness, flowId, requiredString(flow.draftRevisionId, "Run Flow revisionId"));
12948
+ const draftRevisionId = await addStartTrigger(harness, flowId, requiredString(flow.draftRevisionId, "Run Flow revisionId"));
12684
12949
  equal((await json(await request(harness, `/v1/flows/${flowId}/revisions/${draftRevisionId}/check`, {
12685
12950
  body: JSON.stringify({
12686
12951
  engineContract,
@@ -12804,7 +13069,7 @@ var controlApiConformanceCases = [
12804
13069
  async verify(harness) {
12805
13070
  const flow = await createFlow(harness, "Wait flow", "wait-flow");
12806
13071
  const flowId = requiredString(flow.flowId, "Wait Flow flowId");
12807
- const runPath = `/v1/flows/${flowId}/revisions/${changedRevisionId(await json(await changeRequest(harness, flowId, await addManualTrigger(harness, flowId, requiredString(flow.draftRevisionId, "Wait Flow revisionId")), [{
13072
+ const runPath = `/v1/flows/${flowId}/revisions/${changedRevisionId(await json(await changeRequest(harness, flowId, await addStartTrigger(harness, flowId, requiredString(flow.draftRevisionId, "Wait Flow revisionId")), [{
12808
13073
  kind: "graph.node.create",
12809
13074
  node: {
12810
13075
  inputDefinitions: [{
@@ -12976,7 +13241,7 @@ var publicationControlApiConformanceCases = [
12976
13241
  async verify(harness) {
12977
13242
  const flow = await createFlow(harness, "Enabled flow", "enabled-flow");
12978
13243
  const flowId = requiredString(flow.flowId, "Flow id");
12979
- const revisionId = await addManualTrigger(harness, flowId, requiredString(flow.draftRevisionId, "Draft id"));
13244
+ const revisionId = await addStartTrigger(harness, flowId, requiredString(flow.draftRevisionId, "Draft id"));
12980
13245
  const change = (enabled, expectedPublicationId) => request(harness, `/v1/flows/${flowId}/enabled`, {
12981
13246
  method: "PUT",
12982
13247
  body: JSON.stringify({
@@ -12990,6 +13255,7 @@ var publicationControlApiConformanceCases = [
12990
13255
  const disabled = await json(await change(false, publicationId), 200, "Disable");
12991
13256
  equal(disabled.live, {
12992
13257
  enabled: false,
13258
+ hasStart: true,
12993
13259
  publicationId,
12994
13260
  revisionId
12995
13261
  }, "Disabled summary");
@@ -13021,7 +13287,7 @@ var publicationControlApiConformanceCases = [
13021
13287
  async verify(harness) {
13022
13288
  const flow = await createFlow(harness, "Publication flow", "publication-flow");
13023
13289
  const flowId = requiredString(flow.flowId, "Publication Flow flowId");
13024
- const draftRevisionId = await addManualTrigger(harness, flowId, requiredString(flow.draftRevisionId, "Publication Flow revisionId"));
13290
+ const draftRevisionId = await addStartTrigger(harness, flowId, requiredString(flow.draftRevisionId, "Publication Flow revisionId"));
13025
13291
  equal((await json(await request(harness, `/v1/flows/${flowId}/live`), 200, "Read Live")).status, "not-published", "Initial Live status");
13026
13292
  const publish = () => publishRequest(harness, flowId, draftRevisionId, null, "publication-first");
13027
13293
  const completed = await completePublish(harness, await publish(), 202, "Publish Flow");
@@ -13054,7 +13320,7 @@ var publicationControlApiConformanceCases = [
13054
13320
  async verify(harness) {
13055
13321
  const flow = await createFlow(harness, "Rollback flow", "rollback-flow");
13056
13322
  const flowId = requiredString(flow.flowId, "Rollback Flow flowId");
13057
- const firstRevisionId = await addManualTrigger(harness, flowId, requiredString(flow.draftRevisionId, "Rollback Flow revisionId"));
13323
+ const firstRevisionId = await addStartTrigger(harness, flowId, requiredString(flow.draftRevisionId, "Rollback Flow revisionId"));
13058
13324
  const layoutApi = client(harness);
13059
13325
  const initialLayout = await layoutApi.getPresentation(flowId);
13060
13326
  const publishedLayout = await json(await request(harness, `/v1/flows/${flowId}/presentation`, {
@@ -13415,7 +13681,7 @@ function selectableConnectorAccessControlApiConformanceCases(fixture) {
13415
13681
  equal(record(binding, "Selected Connector access binding").connectionDisplayName, fixture.connectionDisplayName, "Selected Provider access binding connection display name");
13416
13682
  equal(record(binding, "Selected Connector access binding").permissionGroupName, fixture.permissionGroupName, "Selected Provider access binding permission group name");
13417
13683
  const selectedDigest = requiredString(selected.sharedAccessDigest, "Selected Connector access digest");
13418
- const revisionId = await addManualTrigger(harness, flowId, requiredString(created.draftRevisionId, "Draft Revision ID"));
13684
+ const revisionId = await addStartTrigger(harness, flowId, requiredString(created.draftRevisionId, "Draft Revision ID"));
13419
13685
  equal((await json(await request(harness, `/v1/flows/${flowId}/revisions/${revisionId}/runs`, {
13420
13686
  body: JSON.stringify({
13421
13687
  engineContract,