@oomol-lab/open-flow 0.1.0-beta.55 → 0.1.0-beta.57

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 (51) hide show
  1. package/README.md +1 -1
  2. package/dist/browser/{createResourceDialog-4H5_lZ6s.js → createResourceDialog-C23SBjYd.js} +2 -2
  3. package/dist/browser/flow-authoring-edge.d.ts +3 -3
  4. package/dist/browser/flow-authoring-node.d.ts +30 -46
  5. package/dist/browser/flow-authoring.js +9215 -21030
  6. package/dist/browser/flow-change-schema.d.ts +267 -1
  7. package/dist/browser/flow-change.d.ts +19 -104
  8. package/dist/browser/flow-change.js +154 -298
  9. package/dist/browser/{flowChanges-ZzG-f9cg.js → flowChanges-fBiAeTzR.js} +2347 -2216
  10. package/dist/browser/{flowWorkspace-ChpRaTMX.js → flowWorkspace-MqcEfg7T.js} +118 -293
  11. package/dist/browser/{icons-CdAB9wyS.js → icons-6oQ8Q9Wm.js} +4309 -4454
  12. package/dist/browser/lib-DrKav3HG.js +11403 -0
  13. package/dist/browser/preview.css +1 -1
  14. package/dist/browser/preview.js +9609 -9548
  15. package/dist/browser/ui-idTooltip.d.ts +11 -0
  16. package/dist/browser/ui.d.ts +5 -0
  17. package/dist/browser/ui.js +83 -1
  18. package/dist/browser/workbench.css +1 -1
  19. package/dist/browser/workbench.js +227 -417
  20. package/dist/browser/{workbenchSelect-BRZN4ish.js → workbenchSelect-DpLbIr29.js} +1 -1
  21. package/dist/common/authoring.d.ts +207 -0
  22. package/dist/common/authoringSchema.d.ts +1293 -0
  23. package/dist/common/control-api-conformance.js +1060 -623
  24. package/dist/common/control-api-errors.d.ts +2 -1
  25. package/dist/common/control-api.d.ts +87 -6
  26. package/dist/common/control-api.js +1058 -705
  27. package/dist/common/control-requests.d.ts +128 -0
  28. package/dist/common/control-requests.js +2913 -1145
  29. package/dist/common/decision.js +6337 -6371
  30. package/dist/common/flow-agent.d.ts +1 -1
  31. package/dist/common/flow-connectionUsage.d.ts +1 -2
  32. package/dist/common/flow-encoding.d.ts +2 -4
  33. package/dist/common/flow-encoding.js +131 -182
  34. package/dist/common/flow-graph.d.ts +10 -10
  35. package/dist/common/flow-semantics.d.ts +13 -9
  36. package/dist/common/flow-semantics.js +9051 -9232
  37. package/dist/common/flowInspection.d.ts +3 -21
  38. package/dist/common/integration-trigger.js +8653 -8687
  39. package/dist/common/lib-DrKav3HG.js +11403 -0
  40. package/dist/common/mcp.d.ts +120 -12
  41. package/dist/common/mcp.js +537 -188
  42. package/dist/common/openapi.js +6337 -6371
  43. package/dist/common/poll-trigger.js +8653 -8687
  44. package/dist/common/run-events.js +0 -1
  45. package/dist/common/scheduler.d.ts +3 -9
  46. package/dist/common/scheduler.js +128 -209
  47. package/dist/common/webhook-trigger.js +6337 -6371
  48. package/package.json +7 -1
  49. package/skills/open-flow/SKILL.md +32 -0
  50. package/skills/open-flow/references/flow-authoring.md +356 -0
  51. package/skills/open-flow/references/flow-n8n-conversion.md +196 -0
@@ -2780,6 +2780,9 @@ function handlePipeResult(left, next, ctx) {
2780
2780
  issues: left.issues
2781
2781
  }, ctx);
2782
2782
  }
2783
+ var $ZodPreprocess = /*@__PURE__*/ $constructor("$ZodPreprocess", (inst, def) => {
2784
+ $ZodPipe.init(inst, def);
2785
+ });
2783
2786
  var $ZodReadonly = /*@__PURE__*/ $constructor("$ZodReadonly", (inst, def) => {
2784
2787
  $ZodType.init(inst, def);
2785
2788
  defineLazyInternal(inst, "propValues", (zod) => zod.def.innerType._zod.propValues);
@@ -5580,7 +5583,7 @@ var ZodRecord = /*@__PURE__*/ $constructor("ZodRecord", (inst, def) => {
5580
5583
  inst.keyType = def.keyType;
5581
5584
  inst.valueType = def.valueType;
5582
5585
  });
5583
- function record$1(keyType, valueType, params) {
5586
+ function record$2(keyType, valueType, params) {
5584
5587
  if (!valueType || !valueType._zod) return new ZodRecord({
5585
5588
  type: "record",
5586
5589
  keyType: string$1(),
@@ -5789,6 +5792,10 @@ function pipe(in_, out) {
5789
5792
  out
5790
5793
  });
5791
5794
  }
5795
+ var ZodPreprocess = /*@__PURE__*/ $constructor("ZodPreprocess", (inst, def) => {
5796
+ ZodPipe.init(inst, def);
5797
+ $ZodPreprocess.init(inst, def);
5798
+ });
5792
5799
  var ZodReadonly = /*@__PURE__*/ $constructor("ZodReadonly", (inst, def) => {
5793
5800
  $ZodReadonly.init(inst, def);
5794
5801
  ZodType.init(inst, def);
@@ -5824,7 +5831,7 @@ function refine(fn, _params = {}) {
5824
5831
  function superRefine(fn, params) {
5825
5832
  return /* @__PURE__ */ _superRefine(fn, params);
5826
5833
  }
5827
- function json$3(params) {
5834
+ function json$4(params) {
5828
5835
  const jsonSchema = lazy(() => {
5829
5836
  return union([
5830
5837
  string$1(params),
@@ -5832,11 +5839,18 @@ function json$3(params) {
5832
5839
  boolean(),
5833
5840
  _null(),
5834
5841
  array(jsonSchema),
5835
- record$1(string$1(), jsonSchema)
5842
+ record$2(string$1(), jsonSchema)
5836
5843
  ]);
5837
5844
  });
5838
5845
  return jsonSchema;
5839
5846
  }
5847
+ function preprocess(fn, schema) {
5848
+ return new ZodPreprocess({
5849
+ type: "pipe",
5850
+ in: transform(fn),
5851
+ out: schema
5852
+ });
5853
+ }
5840
5854
  //#endregion
5841
5855
  //#region ../../node_modules/.bun/dequal@2.0.3/node_modules/dequal/lite/index.mjs
5842
5856
  var has = Object.prototype.hasOwnProperty;
@@ -5881,9 +5895,9 @@ var waitCommentSchema = string$1().trim().refine((value) => [...value].length <=
5881
5895
  //#region src/openapi/common/authBindings.ts
5882
5896
  /** Never allow credentials to enter a Revision as literal node inputs. */
5883
5897
  function assertOpenApiAuthBindings(document) {
5884
- for (const graph of [document.graph, ...Object.values(document.subflows).map((subflow) => subflow.graph)]) for (const node of Object.values(graph.nodes)) {
5885
- if (node.kind != "task" || node.taskId == null || document.tasks[node.taskId]?.executor.kind != "openapi") continue;
5886
- for (const [handle, mapping] of Object.entries(node.inputs)) if (handle.startsWith("auth.") && (mapping.kind == "value" || mapping.kind == "sources" && mapping.sources.some((source) => source.kind == "flow"))) throw new TypeError("OpenAPI authentication accepts deployment variables and upstream outputs only.");
5898
+ for (const node of Object.values(document.graph.nodes)) {
5899
+ if (node.kind != "task" || !("executor" in node.task) || node.task.executor.kind != "openapi") continue;
5900
+ 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.");
5887
5901
  }
5888
5902
  }
5889
5903
  //#endregion
@@ -6306,7 +6320,7 @@ var ExpressionKind = Object.freeze({
6306
6320
  });
6307
6321
  //#endregion
6308
6322
  //#region src/json-schema-subset/expression/expression.ts
6309
- var expression = (delegate) => (e1, e2) => {
6323
+ var expression$1 = (delegate) => (e1, e2) => {
6310
6324
  const rootNode = {
6311
6325
  parent: null,
6312
6326
  swapped: false,
@@ -8294,7 +8308,7 @@ function checkWithResult(extendsContext, schema1, schema2) {
8294
8308
  const describe = describer();
8295
8309
  const equals = schemaEqualsChecker(extendsContext);
8296
8310
  context.isEquals = wrapEqualsCheckerWithCache(isDeepEquals);
8297
- context.calculate = expression({
8311
+ context.calculate = expression$1({
8298
8312
  describe,
8299
8313
  equals,
8300
8314
  calculate,
@@ -8533,7 +8547,7 @@ var isObject = (x) => x !== null && typeof x === "object";
8533
8547
  var isPlainObject = (x) => isObject(x) && !isArray(x);
8534
8548
  var toPlainObject = (x) => isPlainObject(x) ? x : void 0;
8535
8549
  //#endregion
8536
- //#region src/manifest/common/schemaComparer.ts
8550
+ //#region src/flow/common/schemaComparer.ts
8537
8551
  function isStringLikeSchema(value) {
8538
8552
  return toPlainObject(value)?.type === "string";
8539
8553
  }
@@ -8763,46 +8777,37 @@ var webhookMethods = [
8763
8777
  "DELETE"
8764
8778
  ];
8765
8779
  var text = string$1();
8766
- var json$2 = json$3();
8767
- var strings = array(text);
8780
+ var json$3 = json$4();
8781
+ var strings$1 = array(text);
8768
8782
  var port$1 = object({
8769
8783
  description: text.optional(),
8770
- jsonSchema: json$2,
8784
+ jsonSchema: json$3,
8771
8785
  nullable: boolean(),
8772
8786
  handle: text
8773
8787
  });
8774
- var input = port$1.extend({ value: json$2.optional() });
8788
+ var input = port$1.extend({ value: json$3.optional() });
8775
8789
  var group = object({
8776
8790
  collapsed: boolean().optional(),
8777
8791
  group: text
8778
8792
  });
8779
- var nodeSource = object({
8793
+ var source = union([object({
8780
8794
  kind: literal("node"),
8781
8795
  nodeId: text,
8782
8796
  output: text,
8783
8797
  field: text.optional()
8784
- });
8785
- var flowSource = object({
8786
- kind: literal("flow"),
8787
- input: text
8788
- });
8789
- var source = union([
8790
- nodeSource,
8791
- flowSource,
8792
- object({
8793
- kind: literal("binding"),
8794
- bindingId: text
8795
- })
8796
- ]);
8798
+ }), object({
8799
+ kind: literal("binding"),
8800
+ bindingId: text
8801
+ })]);
8797
8802
  var fixedInput = union([object({ kind: literal("unset") }), object({
8798
8803
  kind: literal("value"),
8799
- value: json$2
8804
+ value: json$3
8800
8805
  })]);
8801
8806
  var mapping = union([fixedInput, object({
8802
8807
  kind: literal("sources"),
8803
8808
  sources: array(source)
8804
8809
  })]);
8805
- var inputs = record$1(text, mapping);
8810
+ var inputs = record$2(text, mapping);
8806
8811
  var ports$1 = {
8807
8812
  inputs: array(union([input, group])),
8808
8813
  outputs: array(union([port$1, group]))
@@ -8847,7 +8852,7 @@ var inline = object({
8847
8852
  });
8848
8853
  var agentValue = union([object({
8849
8854
  kind: literal("value"),
8850
- value: json$2
8855
+ value: json$3
8851
8856
  }), object({
8852
8857
  kind: literal("input"),
8853
8858
  input: text
@@ -8876,10 +8881,10 @@ var decisionQuestion = discriminatedUnion("type", [
8876
8881
  name: text,
8877
8882
  instructions: text,
8878
8883
  type: literal("score"),
8879
- criteria: strings
8884
+ criteria: strings$1
8880
8885
  })
8881
8886
  ]);
8882
- var managed = object({
8887
+ var managedFields = object({
8883
8888
  ...ports$1,
8884
8889
  name: text,
8885
8890
  executor: union([
@@ -8894,7 +8899,7 @@ var managed = object({
8894
8899
  method: text,
8895
8900
  path: text,
8896
8901
  serverUrl: text,
8897
- document: json$2,
8902
+ document: json$3,
8898
8903
  auth: array(object({
8899
8904
  id: text,
8900
8905
  type: _enum([
@@ -8930,17 +8935,20 @@ var managed = object({
8930
8935
  inputs: array(input.extend({ source: agentInput }))
8931
8936
  })),
8932
8937
  notification: object({
8933
- taskId: text,
8938
+ action: text,
8939
+ connectionId: text.optional(),
8940
+ inputDefinitions: array(input),
8934
8941
  messageHandle: text,
8935
- inputs: record$1(text, agentValue)
8942
+ inputs: record$2(text, agentValue)
8936
8943
  }).optional()
8937
8944
  })
8938
8945
  ])
8939
- }).transform(limitDecisionTask);
8940
- var operand = union([object({
8946
+ });
8947
+ var managed = managedFields.transform(limitDecisionTask);
8948
+ var operand$1 = union([object({
8941
8949
  kind: literal("value"),
8942
- value: json$2.optional(),
8943
- jsonSchema: json$2.optional()
8950
+ value: json$3.optional(),
8951
+ jsonSchema: json$3.optional()
8944
8952
  }), object({
8945
8953
  kind: literal("source"),
8946
8954
  source
@@ -8951,7 +8959,7 @@ var condition = {
8951
8959
  description: text.optional(),
8952
8960
  output: text,
8953
8961
  groups: array(object({ expressions: array(object({
8954
- left: operand,
8962
+ left: operand$1,
8955
8963
  operator: _enum([
8956
8964
  "!=",
8957
8965
  "<",
@@ -8974,7 +8982,7 @@ var condition = {
8974
8982
  "notHasValue",
8975
8983
  "startsWith"
8976
8984
  ]),
8977
- right: operand.optional()
8985
+ right: operand$1.optional()
8978
8986
  })) }))
8979
8987
  }))
8980
8988
  };
@@ -8984,10 +8992,10 @@ var wait = {
8984
8992
  };
8985
8993
  var webhookOptions = object({
8986
8994
  allowedMethods: never().optional(),
8987
- allowedOrigins: strings.optional(),
8995
+ allowedOrigins: strings$1.optional(),
8988
8996
  noResponseBody: never().optional(),
8989
8997
  responseData: text.optional(),
8990
- responseHeaders: record$1(text, text).optional(),
8998
+ responseHeaders: record$2(text, text).optional(),
8991
8999
  responseStatusCode: number().int().min(200).max(599).optional()
8992
9000
  });
8993
9001
  var webhook = {
@@ -9043,7 +9051,7 @@ var base = {
9043
9051
  var node = union([
9044
9052
  object({
9045
9053
  ...base,
9046
- inputs: record$1(text, never()),
9054
+ inputs: record$2(text, never()),
9047
9055
  kind: literal("condition"),
9048
9056
  ...condition
9049
9057
  }),
@@ -9053,21 +9061,10 @@ var node = union([
9053
9061
  kind: literal("value"),
9054
9062
  values: array(input)
9055
9063
  }),
9056
- object({
9057
- ...base,
9058
- kind: literal("subflow"),
9059
- subflowId: text
9060
- }),
9061
9064
  object({
9062
9065
  ...base,
9063
9066
  kind: literal("task"),
9064
- task: inline,
9065
- additionalInputs: array(input).optional()
9066
- }),
9067
- object({
9068
- ...base,
9069
- kind: literal("task"),
9070
- taskId: text,
9067
+ task: union([inline, managed]),
9071
9068
  additionalInputs: array(input).optional()
9072
9069
  }),
9073
9070
  strictObject({
@@ -9103,7 +9100,7 @@ var node = union([
9103
9100
  ...trigger,
9104
9101
  kind: literal("poll"),
9105
9102
  connectionId: text.min(1).optional(),
9106
- config: record$1(text, fixedInput),
9103
+ config: record$2(text, fixedInput),
9107
9104
  definition: object({
9108
9105
  ...definition,
9109
9106
  type: literal("poll")
@@ -9114,7 +9111,7 @@ var node = union([
9114
9111
  ...trigger,
9115
9112
  kind: literal("integration"),
9116
9113
  connectionId: text.min(1).optional(),
9117
- config: record$1(text, fixedInput),
9114
+ config: record$2(text, fixedInput),
9118
9115
  definition: object({
9119
9116
  ...definition,
9120
9117
  type: literal("integration"),
@@ -9122,10 +9119,25 @@ var node = union([
9122
9119
  })
9123
9120
  })
9124
9121
  ]);
9125
- var target = union([object({ kind: literal("flow") }), object({
9126
- kind: literal("subflow"),
9127
- id: text
9128
- })]);
9122
+ /** Configuration schemas shared by the node authoring boundary. */
9123
+ var authoringDefinitionSchemas = {
9124
+ input,
9125
+ port: port$1,
9126
+ ports: ports$1,
9127
+ condition: strictObject(condition),
9128
+ wait: strictObject(wait),
9129
+ webhook: strictObject(webhook),
9130
+ schedule: triggerScheduleSchema,
9131
+ capabilities: array(capability),
9132
+ connector: managedFields.shape.executor.options[0].omit({ kind: true }).strict(),
9133
+ openapi: managedFields.shape.executor.options[1].omit({ kind: true }).strict(),
9134
+ decision: managedFields.shape.executor.options[2].omit({ kind: true }).strict(),
9135
+ llm: managedFields.shape.executor.options[3].omit({ kind: true }).strict(),
9136
+ agent: managedFields.shape.executor.options[4].omit({
9137
+ kind: true,
9138
+ notification: true
9139
+ }).strict()
9140
+ };
9129
9141
  var edge = object({
9130
9142
  source: text,
9131
9143
  target: text,
@@ -9133,15 +9145,10 @@ var edge = object({
9133
9145
  });
9134
9146
  var at = {
9135
9147
  nodeId: text,
9136
- target
9148
+ target: never().optional()
9137
9149
  };
9138
- var subflow = object({
9139
- name: text,
9140
- inputs: array(input),
9141
- outputs: array(port$1.extend({ sources: array(union([nodeSource, flowSource])) }))
9142
- });
9143
9150
  var graph = object({
9144
- nodes: record$1(text, node),
9151
+ nodes: record$2(text, node),
9145
9152
  edges: array(edge).default([])
9146
9153
  });
9147
9154
  var binding = object({
@@ -9150,32 +9157,43 @@ var binding = object({
9150
9157
  });
9151
9158
  var module = object({
9152
9159
  name: text,
9153
- imports: strings,
9160
+ imports: strings$1,
9154
9161
  source: text
9155
9162
  });
9156
- var document = object({
9157
- bindings: record$1(text, binding),
9158
- graph,
9159
- subflows: record$1(text, subflow.extend({ graph })),
9160
- tasks: record$1(text, managed)
9161
- });
9163
+ var document = preprocess(rejectRetiredDefinitions, object({
9164
+ bindings: record$2(text, binding),
9165
+ graph
9166
+ }));
9162
9167
  var revision = object({
9163
9168
  modelVersion: union([
9164
9169
  literal(2),
9165
9170
  literal(4),
9166
- literal(5)
9171
+ literal(5),
9172
+ literal(6)
9167
9173
  ]),
9168
9174
  document,
9169
- modules: record$1(text, module)
9175
+ modules: record$2(text, module)
9170
9176
  });
9171
9177
  revision.extend({
9172
9178
  kind: literal("open-flow-flow-revision"),
9173
9179
  version: literal(1)
9174
9180
  });
9181
+ function rejectRetiredDefinitions(value) {
9182
+ const candidate = record$1(value);
9183
+ 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.");
9184
+ if (Object.values(record$1(record$1(candidate.graph).nodes)).some((candidateNode) => Object.hasOwn(record$1(candidateNode), "taskId"))) throw new TypeError("Task references are no longer supported.");
9185
+ const subflows = candidate.subflows;
9186
+ 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.");
9187
+ if (Object.values(record$1(record$1(candidate.graph).nodes)).some((candidateNode) => record$1(candidateNode).kind === "subflow")) throw new TypeError("Subflow nodes are no longer supported.");
9188
+ return value;
9189
+ }
9190
+ function record$1(value) {
9191
+ return value != null && typeof value == "object" && !Array.isArray(value) ? value : {};
9192
+ }
9175
9193
  function decodeRevisionContent(value) {
9176
9194
  checkJsonDepth(value);
9177
9195
  const content = revision.parse(value);
9178
- checkErrorModelVersion(content);
9196
+ checkModelVersion(content);
9179
9197
  assertOpenApiAuthBindings(content.document);
9180
9198
  return content;
9181
9199
  }
@@ -9196,17 +9214,22 @@ var shapes = {
9196
9214
  value: text
9197
9215
  },
9198
9216
  "graph.edge.connect": {
9199
- target,
9200
- edge
9217
+ edge,
9218
+ target: never().optional()
9201
9219
  },
9202
9220
  "graph.edge.disconnect": {
9203
- target,
9204
- edge
9221
+ edge,
9222
+ target: never().optional()
9205
9223
  },
9206
9224
  "graph.node.create": {
9207
9225
  ...at,
9208
9226
  node
9209
9227
  },
9228
+ "graph.node.replace": {
9229
+ ...at,
9230
+ before: node,
9231
+ node
9232
+ },
9210
9233
  "graph.node.delete": at,
9211
9234
  "graph.node.field.set": union([
9212
9235
  object({
@@ -9265,13 +9288,11 @@ var shapes = {
9265
9288
  },
9266
9289
  "graph.node.resolution.set": {
9267
9290
  ...at,
9268
- target: object({ kind: literal("flow") }),
9269
9291
  before: object(wait),
9270
9292
  value: object(wait)
9271
9293
  },
9272
9294
  "graph.node.webhook.set": {
9273
9295
  ...at,
9274
- target: object({ kind: literal("flow") }),
9275
9296
  before: object(webhook),
9276
9297
  value: object(webhook)
9277
9298
  },
@@ -9313,63 +9334,24 @@ var shapes = {
9313
9334
  },
9314
9335
  "module.source.replace": {
9315
9336
  moduleId: text,
9316
- beforeImports: strings,
9337
+ beforeImports: strings$1,
9317
9338
  beforeSource: text,
9318
- imports: strings,
9339
+ imports: strings$1,
9319
9340
  source: text
9320
9341
  },
9321
- "subflow.create": {
9322
- subflowId: text,
9323
- subflow: subflow.extend({ graph })
9324
- },
9325
- "subflow.definition.set": {
9326
- subflowId: text,
9327
- before: subflow,
9328
- definition: subflow
9329
- },
9330
- "subflow.delete": { subflowId: text },
9331
- "task.create": {
9332
- taskId: text,
9333
- task: managed
9334
- },
9335
- "task.delete": { taskId: text },
9336
- "task.connector.connection.set": {
9337
- taskId: text,
9338
- before: text.optional(),
9339
- value: text.optional()
9340
- },
9341
- "task.decision.set": {
9342
- taskId: text,
9343
- before: managed,
9344
- value: managed
9345
- },
9346
- "task.openapi.set": {
9347
- taskId: text,
9348
- before: managed,
9349
- value: managed
9350
- },
9351
- "task.agent.set": {
9352
- taskId: text,
9353
- before: managed,
9354
- value: managed
9355
- },
9356
- "task.llm.mode.set": {
9357
- taskId: text,
9358
- before: _enum(["chat", "json"]),
9359
- value: _enum(["chat", "json"])
9360
- },
9361
- "task.name.set": {
9362
- taskId: text,
9363
- before: text,
9364
- value: text
9342
+ "graph.node.task.set": {
9343
+ ...at,
9344
+ before: union([inline, managed]),
9345
+ value: union([inline, managed])
9365
9346
  }
9366
9347
  };
9367
9348
  array(union([...new Map(Object.entries(shapes).map(([kind, shape]) => [kind, shape instanceof ZodType ? shape : object({
9368
9349
  kind: literal(kind),
9369
9350
  ...shape
9370
9351
  })])).values()])).min(1);
9371
- function checkErrorModelVersion(content) {
9372
- if (content.modelVersion < 5 && [content.document.graph, ...Object.values(content.document.subflows).map((item) => item.graph)].some((item) => Object.values(item.nodes).some((itemNode) => itemNode.kind == "error"))) throw new TypeError("Error workflows require Flow model version 5.");
9352
+ function checkModelVersion(content) {
9353
+ 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.");
9354
+ 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.");
9373
9355
  }
9374
9356
  //#endregion
9375
9357
  //#region src/flow/common/change.ts
@@ -9405,6 +9387,298 @@ function resourceNameIssue(value) {
9405
9387
  if (!/^[\p{L}\p{N}](?:[\p{L}\p{N} _-]*[\p{L}\p{N}])?$/u.test(name)) return "specialCharacter";
9406
9388
  }
9407
9389
  //#endregion
9390
+ //#region src/control/common/authoringLlm.ts
9391
+ var authoringLlmConfiguration = strictObject({
9392
+ mode: _enum(["chat", "json"]),
9393
+ resultSchema: json$4(),
9394
+ model: json$4().optional().describe("Default model settings: {model, temperature?, top_p?, max_tokens?}. A bound model input takes precedence."),
9395
+ template: json$4().optional().describe("Default message templates: [{role: \"system\" | \"user\" | \"assistant\", content: \"Text with {{namedInput}}\"}]."),
9396
+ messages: json$4().optional().describe("Default conversation history, prepended without template interpolation; an array of {role, content} or null.")
9397
+ });
9398
+ //#endregion
9399
+ //#region src/control/common/authoringOpenApi.ts
9400
+ var authenticationSchema = union([
9401
+ strictObject({ schemes: array(string$1().min(1)).describe("One complete security alternative advertised by this operation; [] selects no authentication.") }),
9402
+ strictObject({ type: _enum(["bearer", "basic"]) }),
9403
+ strictObject({
9404
+ type: literal("apiKey"),
9405
+ name: string$1().min(1),
9406
+ in: _enum(["header", "query"])
9407
+ })
9408
+ ]);
9409
+ strictObject({
9410
+ sourceUrl: string$1().min(1),
9411
+ path: string$1().min(1),
9412
+ method: string$1().min(1),
9413
+ serverUrl: string$1().optional(),
9414
+ authentication: authenticationSchema.optional().describe("Omit to use the operation default. Bind credentials through the advertised node inputs.")
9415
+ });
9416
+ //#endregion
9417
+ //#region src/control/common/authoringSchema.ts
9418
+ var id$2 = string$1().min(1);
9419
+ var json$2 = json$4();
9420
+ var patch = record$2(id$2, json$2);
9421
+ var type = _enum([
9422
+ "manual",
9423
+ "webhook",
9424
+ "cron",
9425
+ "error",
9426
+ "poll",
9427
+ "integration",
9428
+ "code",
9429
+ "connector",
9430
+ "agent",
9431
+ "llm",
9432
+ "decision",
9433
+ "openapi",
9434
+ "condition",
9435
+ "value",
9436
+ "wait",
9437
+ "approval"
9438
+ ]);
9439
+ var referenceSchema = id$2.describe("An existing node reference returned by read/search, or $alias for a preceding node.add in this edit batch. For node.add.as \"step\", reference \"$step\", never bare \"step\". Aliases are local to one batch.");
9440
+ var output = strictObject({
9441
+ kind: literal("output"),
9442
+ node: referenceSchema,
9443
+ port: id$2.optional().describe("Omit for a node with one output. For multiple outputs, choose a name from node details."),
9444
+ field: string$1().optional()
9445
+ });
9446
+ var variable$1 = strictObject({
9447
+ kind: literal("variable"),
9448
+ name: id$2
9449
+ });
9450
+ var authoringSourceSchema = union([
9451
+ output,
9452
+ variable$1,
9453
+ strictObject({
9454
+ kind: literal("value"),
9455
+ value: json$2
9456
+ }),
9457
+ strictObject({ kind: literal("unset") }),
9458
+ strictObject({ kind: literal("default") }),
9459
+ strictObject({
9460
+ kind: literal("sources"),
9461
+ sources: array(union([output, variable$1])).min(1)
9462
+ })
9463
+ ]);
9464
+ var operand = union([
9465
+ strictObject({
9466
+ kind: literal("value"),
9467
+ value: json$2.optional(),
9468
+ schema: json$2.optional()
9469
+ }),
9470
+ output,
9471
+ variable$1
9472
+ ]);
9473
+ var agentTool = authoringDefinitionSchemas.agent.shape.tools.element.omit({
9474
+ id: true,
9475
+ inputs: true
9476
+ }).extend({ inputs: record$2(id$2, authoringDefinitionSchemas.agent.shape.tools.element.shape.inputs.element.shape.source).optional().describe("Action input sources by name. The tool resolves types from the Action. New inputs default to model-provided; existing sources are preserved when omitted.") }).strict();
9477
+ var notification = strictObject({
9478
+ ...authoringDefinitionSchemas.connector.shape,
9479
+ messageHandle: id$2,
9480
+ inputs: record$2(id$2, union([strictObject({
9481
+ kind: literal("value"),
9482
+ value: json$2
9483
+ }), strictObject({
9484
+ kind: literal("input"),
9485
+ input: id$2
9486
+ })]))
9487
+ });
9488
+ var field = strictObject({
9489
+ schema: json$2.optional(),
9490
+ nullable: boolean().optional(),
9491
+ description: string$1().optional()
9492
+ });
9493
+ var inputFields = record$2(id$2, 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.");
9494
+ var outputFields = record$2(id$2, field).describe("Code return fields by name. Omitted schema accepts any JSON; omitted nullable is true.");
9495
+ var expression = strictObject({
9496
+ left: operand,
9497
+ operator: authoringDefinitionSchemas.condition.shape.cases.element.shape.groups.element.shape.expressions.element.shape.operator,
9498
+ right: operand.optional()
9499
+ });
9500
+ var all = strictObject({ all: array(expression) });
9501
+ var when = union([
9502
+ expression,
9503
+ all,
9504
+ strictObject({ any: array(union([expression, all])) })
9505
+ ]);
9506
+ strictObject({}), strictObject({ sourceFlowIds: array(id$2).optional() }), authoringDefinitionSchemas.webhook.omit({ bodyFields: true }).extend({ body: inputFields }).strict(), strictObject({ schedule: authoringDefinitionSchemas.schedule }), strictObject({
9507
+ key: id$2,
9508
+ connectionId: id$2.optional(),
9509
+ schedule: authoringDefinitionSchemas.schedule
9510
+ }), strictObject({
9511
+ key: id$2,
9512
+ connectionId: id$2.optional()
9513
+ }), strictObject({
9514
+ inputs: inputFields,
9515
+ outputs: outputFields,
9516
+ capabilities: authoringDefinitionSchemas.capabilities.optional()
9517
+ }), authoringDefinitionSchemas.connector.strict(), authoringDefinitionSchemas.agent.omit({
9518
+ prompt: true,
9519
+ tools: true
9520
+ }).extend({
9521
+ inputs: inputFields,
9522
+ resultSchema: json$2.describe("JSON schema of the final result. Defaults to text. The tool manages the output definition; references can omit port."),
9523
+ tools: array(agentTool),
9524
+ notification: notification.optional()
9525
+ }).strict(), authoringLlmConfiguration.extend({ inputs: inputFields }), authoringDefinitionSchemas.decision, strictObject({
9526
+ match: _enum(["first", "all"]),
9527
+ branches: array(strictObject({
9528
+ name: id$2,
9529
+ description: string$1().optional(),
9530
+ when
9531
+ }))
9532
+ }), strictObject({
9533
+ values: patch,
9534
+ outputs: outputFields
9535
+ }), strictObject({ inputs: inputFields }), strictObject({ inputs: inputFields });
9536
+ var updates = strictObject({
9537
+ name: id$2.optional(),
9538
+ description: string$1().optional(),
9539
+ icon: string$1().optional(),
9540
+ maxExecutions: int().positive().optional(),
9541
+ timeoutMs: number().nonnegative().optional(),
9542
+ config: patch.optional().describe("Recursively merge configuration; omitted fields remain unchanged and arrays replace as a whole. This includes schema objects: {} does not clear an existing schema. Use clear paths to remove fields, e.g. [\"config\",\"inputs\",\"amount\",\"schema\",\"type\"].")
9543
+ });
9544
+ var authoringEditSchema = discriminatedUnion("op", [
9545
+ strictObject({
9546
+ op: literal("node.add"),
9547
+ as: id$2.regex(/^[A-Za-z][\w-]*$/).describe("Unique batch-local alias without the $ prefix. Later edits must reference this new node as $alias; the bare alias is not its node ID."),
9548
+ type,
9549
+ name: id$2,
9550
+ config: patch.optional(),
9551
+ inputs: record$2(id$2, authoringSourceSchema).optional().describe("Input data sources, applied after creation, as input.set operations. Execution edges are separate."),
9552
+ code: string$1().optional(),
9553
+ prompt: string$1().optional()
9554
+ }),
9555
+ strictObject({
9556
+ op: literal("node.update"),
9557
+ node: referenceSchema,
9558
+ set: updates.optional(),
9559
+ clear: array(array(id$2).min(1)).optional()
9560
+ }),
9561
+ strictObject({
9562
+ op: literal("node.remove"),
9563
+ node: referenceSchema
9564
+ }),
9565
+ strictObject({
9566
+ op: literal("input.set"),
9567
+ node: referenceSchema,
9568
+ input: id$2,
9569
+ source: authoringSourceSchema
9570
+ }),
9571
+ strictObject({
9572
+ op: _enum(["edge.connect", "edge.disconnect"]),
9573
+ source: referenceSchema,
9574
+ target: referenceSchema,
9575
+ branch: id$2.optional()
9576
+ }),
9577
+ strictObject({
9578
+ op: literal("text.edit"),
9579
+ node: referenceSchema,
9580
+ field: _enum(["code", "prompt"]),
9581
+ oldText: id$2,
9582
+ newText: string$1()
9583
+ }),
9584
+ strictObject({
9585
+ op: literal("text.set"),
9586
+ node: referenceSchema,
9587
+ field: _enum(["code", "prompt"]),
9588
+ text: string$1()
9589
+ })
9590
+ ]);
9591
+ var authoringRequestSchema = strictObject({
9592
+ baseRevision: id$2,
9593
+ requestId: id$2.max(256),
9594
+ edits: array(authoringEditSchema).min(1).max(1e3)
9595
+ });
9596
+ var authoringReadSchema = strictObject({
9597
+ revision: id$2.optional().describe("Fixed revision from a previous read; omit to read the current draft."),
9598
+ nodes: array(id$2).min(1).max(100).optional().describe("Node references to read in one batch. Mutually exclusive with text. Long texts return metadata."),
9599
+ text: strictObject({
9600
+ node: id$2,
9601
+ field: _enum(["code", "prompt"]),
9602
+ start: int().positive().default(1),
9603
+ lines: int().min(1).max(200).default(80)
9604
+ }).optional().describe("Read code or prompt by line (1-based). Mutually exclusive with nodes. Follow nextStart at the same revision until truncated is false.")
9605
+ }).refine((v) => v.nodes == null || v.text == null, "Choose nodes or text.").meta({
9606
+ not: { required: ["nodes", "text"] },
9607
+ description: "Omit nodes and text for an outline; provide nodes for details, or text for an excerpt."
9608
+ });
9609
+ strictObject({ revisionId: id$2 });
9610
+ var authoringSearchSchema = strictObject({
9611
+ revision: id$2.optional(),
9612
+ query: id$2.max(1e3),
9613
+ type: type.optional(),
9614
+ offset: int().nonnegative().default(0),
9615
+ limit: int().min(1).max(100).default(20)
9616
+ });
9617
+ var authoringSchemaQuery = strictObject({
9618
+ type: type.optional(),
9619
+ action: id$2.optional()
9620
+ }).refine((v) => v.type == null || v.action == null, "Choose type or action.");
9621
+ var authoringDiagnosticSchema = object({
9622
+ code: id$2,
9623
+ message: string$1(),
9624
+ nodes: array(id$2),
9625
+ field: string$1().optional(),
9626
+ line: number().optional(),
9627
+ column: number().optional()
9628
+ });
9629
+ var authoringCheckResponse = object({
9630
+ flowId: id$2,
9631
+ revisionId: id$2,
9632
+ valid: boolean(),
9633
+ diagnostics: array(authoringDiagnosticSchema),
9634
+ version: literal(1)
9635
+ });
9636
+ var authoringEditResponse = object({
9637
+ flowId: id$2,
9638
+ saved: literal(true),
9639
+ revision: id$2,
9640
+ nodes: record$2(id$2, id$2),
9641
+ changes: array(object({
9642
+ index: int(),
9643
+ op: id$2,
9644
+ node: id$2.optional()
9645
+ })),
9646
+ validation: object({
9647
+ status: _enum([
9648
+ "valid",
9649
+ "invalid",
9650
+ "unavailable"
9651
+ ]),
9652
+ diagnostics: array(authoringDiagnosticSchema).optional()
9653
+ }),
9654
+ version: literal(1)
9655
+ });
9656
+ var authoringReadResponse = object({
9657
+ flowId: id$2,
9658
+ revision: id$2,
9659
+ data: object({
9660
+ nodes: array(record$2(string$1(), json$2)).optional(),
9661
+ edges: array(json$2).optional(),
9662
+ text: record$2(string$1(), json$2).optional()
9663
+ }),
9664
+ version: literal(1)
9665
+ });
9666
+ var authoringSearchResponse = object({
9667
+ flowId: id$2,
9668
+ revision: id$2,
9669
+ data: object({
9670
+ matches: array(object({
9671
+ node: id$2,
9672
+ field: id$2,
9673
+ line: int().optional(),
9674
+ excerpt: string$1()
9675
+ })),
9676
+ total: int(),
9677
+ nextOffset: int().optional()
9678
+ }),
9679
+ version: literal(1)
9680
+ });
9681
+ //#endregion
9408
9682
  //#region src/control/common/resultQuery.ts
9409
9683
  var resultQuerySchema = strictObject({
9410
9684
  pointer: string$1().max(4096).default(""),
@@ -9498,31 +9772,42 @@ var controlErrorCode = {
9498
9772
  };
9499
9773
  controlErrorCode.eventSourceInvalid, controlErrorCode.eventSourceIdentityUnavailable, controlErrorCode.eventSourceNotFound, controlErrorCode.eventSourceConflict, controlErrorCode.authenticationRequired, controlErrorCode.authorizationDenied, controlErrorCode.bindingUnresolved, controlErrorCode.connectorActionNotFound, controlErrorCode.connectorAccessConflict, controlErrorCode.connectorAccessInvalid, controlErrorCode.connectorAccessRequired, controlErrorCode.connectorAccessUnsupported, controlErrorCode.connectorUnconfigured, controlErrorCode.connectorUnavailable, controlErrorCode.connectorConsoleUnconfigured, controlErrorCode.engineUnavailable, controlErrorCode.engineUnsupported, controlErrorCode.flowInvalid, controlErrorCode.flowRepairRequired, controlErrorCode.flowUpgradeRequired, controlErrorCode.flowNotFound, controlErrorCode.flowBusy, controlErrorCode.flowConflict, controlErrorCode.flowPresentationConflict, controlErrorCode.flowRevisionConflict, controlErrorCode.liveConflict, controlErrorCode.liveNotFound, controlErrorCode.pageInvalidCursor, controlErrorCode.publicationConflict, controlErrorCode.publicationNotFound, controlErrorCode.publicationUnsupported, controlErrorCode.publishOperationNotFound, controlErrorCode.routeNotFound, controlErrorCode.runConflict, controlErrorCode.runEventsExpired, controlErrorCode.runInvalid, controlErrorCode.runNotFound, controlErrorCode.runNotTerminal, controlErrorCode.runOverloaded, controlErrorCode.runWaitNotFound, controlErrorCode.triggerKeyInvalid, controlErrorCode.triggerKeyNotFound, controlErrorCode.triggerNotFound, controlErrorCode.variableInvalid, controlErrorCode.variableLimitReached, controlErrorCode.variableNotFound;
9500
9774
  var ApiError = class extends Error {
9501
- constructor(status, code, message) {
9775
+ constructor(status, code, message, details) {
9502
9776
  super(message);
9503
9777
  this.code = code;
9778
+ this.details = details;
9504
9779
  this.name = "ApiError";
9505
9780
  this.status = status;
9506
9781
  }
9507
9782
  };
9508
9783
  //#endregion
9509
9784
  //#region src/control/common/decoding.ts
9510
- function invalidResponse() {
9511
- throw new ApiError(502, "response.invalid", "The Control API returned an invalid response.");
9785
+ var InvalidResponseError = class extends ApiError {
9786
+ constructor(detail) {
9787
+ super(502, "response.invalid", `The Control API returned an invalid response.${detail == null ? "" : ` ${detail}`}`);
9788
+ this.detail = detail;
9789
+ }
9790
+ };
9791
+ function invalidResponse(detail) {
9792
+ throw new InvalidResponseError(detail);
9512
9793
  }
9513
9794
  function record(value) {
9514
- if (value == null || typeof value != "object" || Array.isArray(value)) return invalidResponse();
9795
+ if (value == null || typeof value != "object" || Array.isArray(value)) return invalidResponse("Expected an object.");
9515
9796
  return value;
9516
9797
  }
9517
9798
  function string(value) {
9518
- return typeof value == "string" && value.length > 0 ? value : invalidResponse();
9799
+ return typeof value == "string" && value.length > 0 ? value : invalidResponse("Expected a non-empty string.");
9519
9800
  }
9520
9801
  function exact(value, keys) {
9521
9802
  const actual = Object.keys(value);
9522
- if (actual.length != keys.length || actual.some((key) => !keys.includes(key))) invalidResponse();
9803
+ if (actual.length != keys.length || actual.some((key) => !keys.includes(key))) {
9804
+ const missing = keys.filter((key) => !Object.hasOwn(value, key));
9805
+ const unexpected = actual.filter((key) => !keys.includes(key));
9806
+ invalidResponse([missing.length > 0 ? `Missing fields: ${missing.join(", ")}.` : "", unexpected.length > 0 ? `Unexpected fields: ${unexpected.join(", ")}.` : ""].filter(Boolean).join(" "));
9807
+ }
9523
9808
  }
9524
9809
  function integer(value) {
9525
- return Number.isSafeInteger(value) ? value : invalidResponse();
9810
+ return Number.isSafeInteger(value) ? value : invalidResponse("Expected a safe integer.");
9526
9811
  }
9527
9812
  function jsonValue(value) {
9528
9813
  if (value === null || typeof value == "boolean" || typeof value == "string") return value;
@@ -9557,10 +9842,19 @@ function accessPermissions(value) {
9557
9842
  "configured",
9558
9843
  "proxy"
9559
9844
  ]);
9560
- if (!Array.isArray(source.triggerIds) || typeof source.allTriggers != "boolean" || !Array.isArray(source.actionIds) || typeof source.allActions != "boolean" || typeof source.configured != "boolean" || typeof source.proxy != "boolean") return invalidResponse();
9845
+ if (!Array.isArray(source.actionIds)) return invalidResponse("permissions.actionIds: expected an array.");
9846
+ if (!Array.isArray(source.triggerIds)) return invalidResponse("permissions.triggerIds: expected an array.");
9847
+ if (typeof source.allActions != "boolean") return invalidResponse("permissions.allActions: expected a boolean.");
9848
+ if (typeof source.allTriggers != "boolean") return invalidResponse("permissions.allTriggers: expected a boolean.");
9849
+ if (typeof source.configured != "boolean") return invalidResponse("permissions.configured: expected a boolean.");
9850
+ if (typeof source.proxy != "boolean") return invalidResponse("permissions.proxy: expected a boolean.");
9561
9851
  const actionIds = source.actionIds.map(string);
9562
9852
  const triggerIds = source.triggerIds.map(string);
9563
- if (new Set(actionIds).size != actionIds.length || source.allActions && actionIds.length != 0 || new Set(triggerIds).size != triggerIds.length || source.allTriggers && triggerIds.length != 0 || source.proxy && (!source.allActions || !source.allTriggers || source.configured)) return invalidResponse();
9853
+ if (new Set(actionIds).size != actionIds.length) return invalidResponse("permissions.actionIds: duplicate IDs.");
9854
+ if (source.allActions && actionIds.length != 0) return invalidResponse("permissions.actionIds: must be empty when allActions is true.");
9855
+ if (new Set(triggerIds).size != triggerIds.length) return invalidResponse("permissions.triggerIds: duplicate IDs.");
9856
+ if (source.allTriggers && triggerIds.length != 0) return invalidResponse("permissions.triggerIds: must be empty when allTriggers is true.");
9857
+ if (source.proxy && (!source.allActions || !source.allTriggers || source.configured)) return invalidResponse("permissions.proxy: requires allActions=true, allTriggers=true and configured=false.");
9564
9858
  return {
9565
9859
  actionIds,
9566
9860
  triggerIds,
@@ -9590,15 +9884,15 @@ function accessBinding(value, candidate) {
9590
9884
  "providerId",
9591
9885
  ...candidate ? [] : ["status"]
9592
9886
  ]);
9593
- if (policyRevision != null && typeof policyRevision != "string") return invalidResponse();
9594
- if (candidate && isDefault !== void 0 && typeof isDefault != "boolean") return invalidResponse();
9595
- if (permissionGroupName !== void 0 && permissionGroupName !== null && typeof permissionGroupName != "string") return invalidResponse();
9887
+ if (policyRevision != null && typeof policyRevision != "string") return invalidResponse("policyRevision: expected a string.");
9888
+ if (candidate && isDefault !== void 0 && typeof isDefault != "boolean") return invalidResponse("isDefault: expected a boolean.");
9889
+ if (permissionGroupName !== void 0 && permissionGroupName !== null && typeof permissionGroupName != "string") return invalidResponse("permissionGroupName: expected a string or null.");
9596
9890
  if (!candidate && status != "active" && status != "forbidden" && status != "invalid" && status != "missing") return invalidResponse();
9597
9891
  let bindingSource;
9598
9892
  try {
9599
9893
  bindingSource = parseProviderAccessSource(source.source);
9600
9894
  } catch {
9601
- return invalidResponse();
9895
+ return invalidResponse("source: expected { kind: 'admin-delegation' } or { kind: 'policy', ruleId: string | null }.");
9602
9896
  }
9603
9897
  return {
9604
9898
  accessBindingId: string(source.accessBindingId),
@@ -9614,7 +9908,7 @@ function accessBinding(value, candidate) {
9614
9908
  };
9615
9909
  }
9616
9910
  function accessMode(value) {
9617
- if (value != "implicit" && value != "selectable") return invalidResponse();
9911
+ if (value != "implicit" && value != "selectable") return invalidResponse("mode: expected implicit or selectable.");
9618
9912
  return value;
9619
9913
  }
9620
9914
  function connectorAccess(value) {
@@ -9723,10 +10017,12 @@ function connectorAccessCandidates(value, providerId) {
9723
10017
  "providerId",
9724
10018
  "version"
9725
10019
  ]);
9726
- if (source.version != 1 || string(source.providerId) != providerId || !Array.isArray(source.candidates)) return invalidResponse();
10020
+ if (source.version != 1) return invalidResponse("version: expected 1.");
10021
+ if (string(source.providerId) != providerId) return invalidResponse("providerId: does not match the requested provider.");
10022
+ if (!Array.isArray(source.candidates)) return invalidResponse("candidates: expected an array.");
9727
10023
  const candidates = source.candidates.map((candidate) => accessBinding(candidate, true));
9728
- if (candidates.some((candidate) => candidate.providerId != providerId)) return invalidResponse();
9729
- if (new Set(candidates.map((candidate) => candidate.accessBindingId)).size != candidates.length) return invalidResponse();
10024
+ if (candidates.some((candidate) => candidate.providerId != providerId)) return invalidResponse("candidates[].providerId: does not match the requested provider.");
10025
+ if (new Set(candidates.map((candidate) => candidate.accessBindingId)).size != candidates.length) return invalidResponse("candidates[].accessBindingId: duplicate IDs.");
9730
10026
  return {
9731
10027
  candidates,
9732
10028
  mode: accessMode(source.mode),
@@ -9737,12 +10033,13 @@ function connectorAccessCandidates(value, providerId) {
9737
10033
  function connectorAccessCandidatesBatch(value, providerIds) {
9738
10034
  const source = record(value);
9739
10035
  exact(source, ["results", "version"]);
9740
- if (source.version != 1 || !Array.isArray(source.results)) return invalidResponse();
10036
+ if (source.version != 1) return invalidResponse("version: expected 1.");
10037
+ if (!Array.isArray(source.results)) return invalidResponse("results: expected an array.");
9741
10038
  const remaining = new Set(providerIds);
9742
10039
  const results = source.results.map((entry) => {
9743
10040
  const item = record(entry);
9744
10041
  const providerId = string(item.providerId);
9745
- if (!remaining.delete(providerId)) return invalidResponse();
10042
+ if (!remaining.delete(providerId)) return invalidResponse("results[].providerId: duplicate or unrequested provider.");
9746
10043
  if (!Object.hasOwn(item, "error")) return connectorAccessCandidates(item, providerId);
9747
10044
  exact(item, ["providerId", "error"]);
9748
10045
  const error = record(item.error);
@@ -9755,7 +10052,7 @@ function connectorAccessCandidatesBatch(value, providerIds) {
9755
10052
  }
9756
10053
  };
9757
10054
  });
9758
- if (remaining.size != 0) return invalidResponse();
10055
+ if (remaining.size != 0) return invalidResponse("results: missing requested providers.");
9759
10056
  return {
9760
10057
  results,
9761
10058
  version: 1
@@ -9943,9 +10240,9 @@ function isUiLanguage(value) {
9943
10240
  var configInputsSchema = array(union([strictObject({
9944
10241
  handle: string$1().min(1),
9945
10242
  description: string$1().optional(),
9946
- jsonSchema: json$3(),
10243
+ jsonSchema: json$4(),
9947
10244
  nullable: boolean(),
9948
- value: json$3().optional()
10245
+ value: json$4().optional()
9949
10246
  }), strictObject({
9950
10247
  group: string$1(),
9951
10248
  collapsed: boolean().optional()
@@ -10178,7 +10475,7 @@ function labels(value, handles) {
10178
10475
  }
10179
10476
  //#endregion
10180
10477
  //#region src/control/common/results.ts
10181
- var json$1 = json$3();
10478
+ var json$1 = json$4();
10182
10479
  var entry = strictObject({
10183
10480
  pointer: string$1(),
10184
10481
  type: _enum([
@@ -10342,6 +10639,43 @@ function connectorConnectionsQuery(serviceId, flowId) {
10342
10639
  }
10343
10640
  //#endregion
10344
10641
  //#region src/control/common/flowDecoders.ts
10642
+ function strings(value) {
10643
+ return Array.isArray(value) ? value.map(string) : invalidResponse();
10644
+ }
10645
+ function resourceReferences(input) {
10646
+ const source = record(input);
10647
+ const draft = source.draft === null ? null : record(source.draft);
10648
+ const shared = record(source.sharedAccess);
10649
+ if (draft != null && !Array.isArray(draft.connections)) return invalidResponse();
10650
+ if (!Array.isArray(shared.bindings)) return invalidResponse();
10651
+ const accessRevision = integer(shared.accessRevision);
10652
+ if (accessRevision < 0) return invalidResponse();
10653
+ return {
10654
+ draft: draft == null ? null : {
10655
+ variableNames: strings(draft.variableNames),
10656
+ errorSourceFlowIds: strings(draft.errorSourceFlowIds),
10657
+ connections: draft.connections.map((value) => {
10658
+ const connection = record(value);
10659
+ return {
10660
+ providerId: string(connection.providerId),
10661
+ connectionId: string(connection.connectionId)
10662
+ };
10663
+ })
10664
+ },
10665
+ sharedAccess: {
10666
+ accessRevision,
10667
+ providerIds: strings(shared.providerIds),
10668
+ bindings: shared.bindings.map((value) => {
10669
+ const binding = record(value);
10670
+ return {
10671
+ providerId: string(binding.providerId),
10672
+ connectionId: binding.connectionId === null ? null : string(binding.connectionId),
10673
+ accessBindingId: string(binding.accessBindingId)
10674
+ };
10675
+ })
10676
+ }
10677
+ };
10678
+ }
10345
10679
  function flow$1(value) {
10346
10680
  const source = record(value);
10347
10681
  const status = source.status;
@@ -10358,6 +10692,7 @@ function flow$1(value) {
10358
10692
  createdAt: string(source.createdAt),
10359
10693
  ...source.connectorTeamId == null ? {} : { connectorTeamId: string(source.connectorTeamId) },
10360
10694
  draftRevisionId: string(source.draftRevisionId),
10695
+ resourceReferences: resourceReferences(source.resourceReferences),
10361
10696
  flowId: string(source.flowId),
10362
10697
  name: string(source.name),
10363
10698
  status,
@@ -10938,7 +11273,7 @@ function decodeRunEvent(value) {
10938
11273
  switch (kind) {
10939
11274
  case "node.started": {
10940
11275
  const nodeKind = payload.nodeKind;
10941
- if (nodeKind !== void 0 && nodeKind !== "approval" && nodeKind !== "condition" && nodeKind !== "connector" && nodeKind !== "javascript" && nodeKind !== "decision" && nodeKind !== "openapi" && nodeKind !== "llm" && nodeKind !== "agent" && nodeKind !== "subflow" && nodeKind !== "value" && nodeKind !== "wait") return invalidResponse();
11276
+ 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();
10942
11277
  return {
10943
11278
  ...base,
10944
11279
  kind,
@@ -11424,6 +11759,37 @@ var ControlClient = class {
11424
11759
  return invalidResponse();
11425
11760
  }
11426
11761
  }
11762
+ async readAuthoring(flowId, query = {}) {
11763
+ return authoringReadResponse.parse(await this.request(`/v1/flows/${segment(flowId)}/authoring/read`, {
11764
+ method: "POST",
11765
+ body: JSON.stringify(query)
11766
+ }));
11767
+ }
11768
+ async searchAuthoring(flowId, query) {
11769
+ return authoringSearchResponse.parse(await this.request(`/v1/flows/${segment(flowId)}/authoring/search`, {
11770
+ method: "POST",
11771
+ body: JSON.stringify(query)
11772
+ }));
11773
+ }
11774
+ async authoringSchema(flowId, query) {
11775
+ return record(await this.request(`/v1/flows/${segment(flowId)}/authoring/schema`, {
11776
+ method: "POST",
11777
+ body: JSON.stringify(query)
11778
+ }));
11779
+ }
11780
+ async editAuthoring(flowId, request) {
11781
+ return authoringEditResponse.parse(await this.request(`/v1/flows/${segment(flowId)}/authoring/edit`, {
11782
+ method: "POST",
11783
+ headers: { "idempotency-key": request.requestId },
11784
+ body: JSON.stringify(request)
11785
+ }));
11786
+ }
11787
+ async checkAuthoring(flowId, revisionId) {
11788
+ return authoringCheckResponse.parse(await this.request(`/v1/flows/${segment(flowId)}/authoring/check`, {
11789
+ method: "POST",
11790
+ body: JSON.stringify({ revisionId })
11791
+ }));
11792
+ }
11427
11793
  async changeDraft(flowId, expectedRevisionId, operations, changeId = operationKey("change")) {
11428
11794
  return draftChange(await this.request(`/v1/flows/${segment(flowId)}/draft/changes`, {
11429
11795
  body: JSON.stringify({
@@ -11606,7 +11972,7 @@ var ControlClient = class {
11606
11972
  }
11607
11973
  const error = record(value).error;
11608
11974
  const source = error == null ? void 0 : record(error);
11609
- throw new ApiError(response.status, typeof source?.code == "string" ? source.code : "request.failed", typeof source?.message == "string" ? source.message : `Request failed with status ${response.status}.`);
11975
+ throw new ApiError(response.status, typeof source?.code == "string" ? source.code : "request.failed", typeof source?.message == "string" ? source.message : `Request failed with status ${response.status}.`, source?.details == null ? void 0 : record(source.details));
11610
11976
  }
11611
11977
  return response;
11612
11978
  }
@@ -11679,7 +12045,6 @@ var mcpConformanceCases = [
11679
12045
  const flow = await client.createFlow("MCP Run listing");
11680
12046
  const changed = await client.changeDraft(flow.flowId, flow.draftRevisionId, [{
11681
12047
  kind: "graph.node.create",
11682
- target: { kind: "flow" },
11683
12048
  nodeId: "start",
11684
12049
  node: {
11685
12050
  kind: "manual",
@@ -11785,13 +12150,13 @@ var mcpConformanceCases = [
11785
12150
  //#endregion
11786
12151
  //#region src/control/common/mcp.ts
11787
12152
  var mcpProtocolVersion = "2026-07-28";
11788
- var json = json$3();
12153
+ var json = json$4();
11789
12154
  var id = string$1().min(1);
11790
12155
  var mutationKey = id.max(256).describe("Stable identity for this mutation. Retry with the same key and identical arguments, even after a lost response.");
11791
12156
  var pageLimit = int().min(1).max(100).default(50);
11792
12157
  var flow = id.describe("Exact Flow ID returned by flow_list or flow_create.");
11793
12158
  var run = id.describe("Exact Run ID returned by flow_run or run_list.");
11794
- var mcpInstructions = "Use flow_list and flow_get to inspect a Flow. Use flow_node_get with the observed revisionId for individual node schemas or code. Use flow_schema to learn atomic edit operations, then flow_apply with the observed expectedRevisionId and a stable idempotencyKey. Use flow_check before flow_run. Select an explicit Trigger node ID and fixed revision or publication. A new Flow has no Trigger until you add one. Before adding a Feishu Trigger, use event_source_list and compare its Connection IDs with connector_connections in the Flow scope. If no source is available, create and verify one in Workbench. Use flow_publish to publish a fixed Revision, then poll flow_publish_status until succeeded or failed. Use flow_set_enabled to enable or disable the observed Live publication. flow_run returns an accepted Run, not its final result. Find Runs with run_list, poll run_get and use run_result after terminal. Resolve a waiting Run only with an explicit run_resolve_wait action allowed by run_get. Use run_results and run_result_read to inspect stored Agent tool results; these are separate from the terminal Run result. Retry flow_create, flow_apply, flow_publish and flow_run only with identical arguments and the same idempotencyKey; a new key can execute the Flow again. Other mutations use the same resource identity and arguments when retrying. Cancel a Run explicitly with run_cancel. Use nextCursor and nextAfter to read subsequent pages. Connector-backed deployments may require a Team; inspect connector_teams before creating a Flow.";
12159
+ var mcpInstructions = "Use flow_list, flow_read and flow_search to inspect root workflows. Read node type schemas with flow_schema. Use flow_edit with the observed baseRevision and a stable requestId. Node edits affect only the selected node. Text edits require exactly one match. Execution edges and input sources are independent. Legacy Subflow content is unsupported. Edits can save incomplete drafts; inspect returned diagnostics and use flow_check before running. Use flow_check before flow_run. Select an explicit Trigger node ID and fixed revision or publication. A new Flow has no Trigger until you add one. Before adding a Feishu Trigger, use event_source_list and compare its Connection IDs with connector_connections in the Flow scope. If no source is available, create and verify one in Workbench. Use flow_publish to publish a fixed Revision, then poll flow_publish_status until succeeded or failed. Use flow_set_enabled to enable or disable the observed Live publication. flow_run returns an accepted Run, not its final result. Find Runs with run_list, poll run_get and use run_result after terminal. Resolve a waiting Run only with an explicit run_resolve_wait action allowed by run_get. Use run_results and run_result_read to inspect stored Agent tool results; these are separate from the terminal Run result. Retry flow_edit with identical arguments and the same requestId. Retry flow_create, flow_publish and flow_run only with identical arguments and the same idempotencyKey; a new key can execute the Flow again. Other mutations use the same resource identity and arguments when retrying. Cancel a Run explicitly with run_cancel. Use nextCursor and nextAfter to read subsequent pages. Connector-backed deployments may require a Team; inspect connector_teams before creating a Flow.";
11795
12160
  function tool(description, schema, readOnly) {
11796
12161
  return {
11797
12162
  description,
@@ -11823,32 +12188,16 @@ var mcpTools = {
11823
12188
  cursor: id.optional(),
11824
12189
  limit: pageLimit
11825
12190
  }), true),
11826
- flow_get: tool("Read a compact Draft graph with input bindings, port handles, subflows and Live status. Use full=true for complete Revision content, schemas, source code and exact before values required by complex edits. Unreadable Drafts return draft=null and draftIssue; flow.live still identifies the published version. Use draft.revisionId as the base of an edit.", strictObject({
11827
- flowId: flow,
11828
- full: boolean().optional()
11829
- }), true),
11830
- flow_node_get: tool("Read one node and its Task definition or code module from a fixed Revision. Omit subflowId for the root graph. Use revisionId from flow_get; the returned node contains exact before values for edits.", strictObject({
11831
- flowId: flow,
11832
- revisionId: id,
11833
- nodeId: id,
11834
- subflowId: id.optional()
11835
- }), true),
11836
- flow_schema: tool("Get an operation schema by kind, or a complete apply batch by example (connector, poll, poll-notification, code, wait). Use example=index to list examples. graph.trigger.create resolves a provider key into a fixed definition at commit.", strictObject({
11837
- kind: id.optional(),
11838
- example: id.optional()
11839
- }).refine((value) => value.kind == null || value.example == null, "Choose kind or example, not both."), true),
12191
+ flow_read: tool("Read an outline, selected node details, or a bounded code/prompt excerpt. Carry the returned revision into subsequent reads and edits.", authoringReadSchema.safeExtend({ flowId: flow }).meta({ ...authoringReadSchema.meta() }), true),
12192
+ flow_search: tool("Find nodes by name, configuration or source text in a fixed Revision. Follow nextOffset for more matches.", authoringSearchSchema.extend({ flowId: flow }), true),
12193
+ flow_schema: tool("Read node configuration schemas and the edit grammar, or an Action contract. Action lookup requires a flowId.", authoringSchemaQuery.safeExtend({ flowId: flow.optional() }), true),
11840
12194
  flow_create: tool("Create an empty Flow. If this deployment uses OOMOL Connector, choose a teamId from connector_teams. Keep the key and arguments stable when retrying.", strictObject({
11841
12195
  name: id.refine((name) => name == name.trim() && resourceNameIssue(name) == null, "Flow name is invalid."),
11842
12196
  idempotencyKey: mutationKey,
11843
12197
  teamId: id.optional()
11844
12198
  }), false),
11845
- flow_apply: tool("Apply ordered atomic changes. Read flow_schema first. A stale expectedRevisionId is a conflict; reread the Draft before deciding on a new edit.", strictObject({
11846
- flowId: flow,
11847
- expectedRevisionId: id,
11848
- idempotencyKey: mutationKey,
11849
- operations: array(json).min(1).describe("Change operations defined by flow_schema. Explicit IDs and before values refer to the base Revision.")
11850
- }), false),
11851
- flow_check: tool("Validate a fixed Revision and return diagnostics. Get its revisionId from flow_get or flow_apply.", strictObject({
12199
+ flow_edit: tool("Atomically edit root nodes, input sources, execution edges and text. Use $alias for preceding creations. Preserve baseRevision and requestId when retrying. A saved draft may have validation diagnostics.", authoringRequestSchema.extend({ flowId: flow }), false),
12200
+ flow_check: tool("Validate a fixed Revision and return diagnostics. Use the revision returned by flow_read or flow_edit as revisionId.", strictObject({
11852
12201
  flowId: flow,
11853
12202
  revisionId: id
11854
12203
  }), true),
@@ -11862,7 +12211,7 @@ var mcpTools = {
11862
12211
  flowId: flow,
11863
12212
  operationId: id
11864
12213
  }), true),
11865
- flow_set_enabled: tool("Enable or disable a published Flow. Supply expectedPublicationId from flow_get; a changed Live publication is a conflict. This does not cancel accepted Runs; use run_cancel for those.", strictObject({
12214
+ flow_set_enabled: tool("Enable or disable a published Flow. Supply expectedPublicationId from flow_list; a changed Live publication is a conflict. This does not cancel accepted Runs; use run_cancel for those.", strictObject({
11866
12215
  flowId: flow,
11867
12216
  expectedPublicationId: id,
11868
12217
  enabled: boolean()
@@ -11873,18 +12222,18 @@ var mcpTools = {
11873
12222
  revisionId: id,
11874
12223
  trigger: strictObject({
11875
12224
  nodeId: id,
11876
- outputs: record$1(string$1(), json)
12225
+ outputs: record$2(string$1(), json)
11877
12226
  }),
11878
- inputs: record$1(string$1(), record$1(string$1(), json)).default({}),
12227
+ inputs: record$2(string$1(), record$2(string$1(), json)).default({}),
11879
12228
  idempotencyKey: mutationKey
11880
12229
  }), strictObject({
11881
12230
  source: literal("live"),
11882
12231
  publicationId: id,
11883
12232
  trigger: strictObject({
11884
12233
  nodeId: id,
11885
- outputs: record$1(string$1(), json)
12234
+ outputs: record$2(string$1(), json)
11886
12235
  }),
11887
- inputs: record$1(string$1(), record$1(string$1(), json)).default({}),
12236
+ inputs: record$2(string$1(), record$2(string$1(), json)).default({}),
11888
12237
  idempotencyKey: mutationKey
11889
12238
  })]).meta({ type: "object" }), false),
11890
12239
  run_list: tool("List Runs for a Flow, optionally filtered by status. Continue with nextCursor; cursors are compatible with the Control API.", strictObject({
@@ -11957,7 +12306,7 @@ var mcpTools = {
11957
12306
  flowId: flow.optional()
11958
12307
  }), true),
11959
12308
  event_source_list: tool("List independent Feishu event sources, including Team, Connection, event types, enabled and verification status. Inspect consumers for Flows actually using each source.", strictObject({}), true),
11960
- trigger_search: tool("Search provider Trigger summaries; omit query to list all. Flow trigger instances are in flow_get. Manual, Webhook and Cron are built-in node kinds described by flow_schema.", strictObject({ query: string$1().trim().min(1).max(256).optional() }), true),
12309
+ trigger_search: tool("Search provider Trigger summaries; omit query to list all. Flow trigger instances are in flow_read. Manual, Webhook and Cron are built-in node kinds described by flow_schema.", strictObject({ query: string$1().trim().min(1).max(256).optional() }), true),
11961
12310
  trigger_get: tool("Read a provider Trigger definition before creating its node.", strictObject({ key: id }), true)
11962
12311
  };
11963
12312
  //#endregion