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

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 (55) hide show
  1. package/dist/browser/{createResourceDialog-DZgJsr3e.js → createResourceDialog-BAJXbzNH.js} +20 -7
  2. package/dist/browser/flow-authoring.js +8 -7
  3. package/dist/browser/flow-change-schema.d.ts +1 -0
  4. package/dist/browser/flow-change.d.ts +1 -0
  5. package/dist/browser/flow-change.js +8 -7
  6. package/dist/browser/flow-notifications.d.ts +6 -0
  7. package/dist/browser/{flowChanges-CzYIVevI.js → flowChanges-BAMkSaKF.js} +1771 -1331
  8. package/dist/browser/{flowRunInputEditorStore-Dsxyfwae.js → flowRunInputEditorStore-B2Rw4VsT.js} +1 -1
  9. package/dist/browser/{flowWorkspace-BgZaFKZm.js → flowWorkspace-DxLc1Ybv.js} +429 -205
  10. package/dist/browser/{icons-CajfDpy_.js → icons-Db2Jb2iX.js} +30 -10
  11. package/dist/browser/preview.css +40 -52
  12. package/dist/browser/preview.js +7752 -7452
  13. package/dist/browser/theme.css +4 -0
  14. package/dist/browser/{typeScriptSession-fXPMFGjW.js → typeScriptSession-D0bjYDeg.js} +1 -1
  15. package/dist/browser/ui.css +39 -51
  16. package/dist/browser/ui.js +5 -5
  17. package/dist/browser/{value-DL_poNiC.js → value-BADHeZ9I.js} +12 -1
  18. package/dist/browser/workbench-contract.d.ts +10 -0
  19. package/dist/browser/workbench.css +43 -59
  20. package/dist/browser/workbench.d.ts +5 -3
  21. package/dist/browser/workbench.js +255 -216
  22. package/dist/browser/{workbenchSelect-H9wzEFkH.js → workbenchSelect-C-jf6NIM.js} +1 -1
  23. package/dist/command/index.js +49 -48
  24. package/dist/common/authoringSchema.d.ts +1 -0
  25. package/dist/common/canvas-commands.d.ts +19 -0
  26. package/dist/common/connector-action.d.ts +1 -0
  27. package/dist/common/connector-action.js +15 -12
  28. package/dist/common/control-api-conformance.js +127 -8
  29. package/dist/common/control-api.d.ts +16 -0
  30. package/dist/common/control-api.js +67 -8
  31. package/dist/common/control-requests.d.ts +23 -0
  32. package/dist/common/control-requests.js +64 -19
  33. package/dist/common/decision.js +8 -7
  34. package/dist/common/flow-connectionUsage.d.ts +1 -0
  35. package/dist/common/flow-encoding.d.ts +1 -0
  36. package/dist/common/flow-encoding.js +202 -10
  37. package/dist/common/flow-notifications.d.ts +6 -0
  38. package/dist/common/flow-semantics.js +64 -46
  39. package/dist/common/flow-workflowFile.d.ts +23 -0
  40. package/dist/common/integration-trigger.js +8 -7
  41. package/dist/common/localization.d.ts +1 -0
  42. package/dist/common/localization.js +12 -1
  43. package/dist/common/mcp.d.ts +103 -0
  44. package/dist/common/mcp.js +135 -11
  45. package/dist/common/openapi.js +8 -7
  46. package/dist/common/poll-trigger.js +8 -7
  47. package/dist/common/runtime-contract.js +1 -1
  48. package/dist/common/scheduler.d.ts +22 -2
  49. package/dist/common/scheduler.js +354 -83
  50. package/dist/common/trigger-config.d.ts +2 -0
  51. package/dist/common/webhook-trigger.js +8 -7
  52. package/dist/index.d.ts +2 -2
  53. package/package.json +1 -1
  54. package/skills/open-flow/SKILL.md +1 -1
  55. package/skills/open-flow/references/flow-authoring.md +49 -0
@@ -7543,10 +7543,10 @@ function compileEnumAndConst(context, enumList, constValue, schema) {
7543
7543
  }
7544
7544
  if (compiledEnum.length === 0) recordWarn(context, "all of elements from list is rejected by currently schema object", "enum");
7545
7545
  }
7546
- if (constValue && valid(schema, constValue) === ValidResult.Invalid) isNever = true;
7546
+ if (constValue !== void 0 && valid(schema, constValue) === ValidResult.Invalid) isNever = true;
7547
7547
  if (compiledEnum) {
7548
7548
  if (compiledEnum.length === 0) isNever = true;
7549
- else if (constValue) {
7549
+ else if (constValue !== void 0) {
7550
7550
  let foundEquals = false;
7551
7551
  for (const enumValue of compiledEnum) if (isDeepEquals(enumValue, constValue)) {
7552
7552
  foundEquals = true;
@@ -7559,7 +7559,7 @@ function compileEnumAndConst(context, enumList, constValue, schema) {
7559
7559
  const compiledSchema = {};
7560
7560
  if (schema.type) compiledSchema.type = schema.type;
7561
7561
  if (compiledEnum) compiledSchema.enum = compiledEnum;
7562
- if (constValue) compiledSchema.const = wrapCompiledValue(deepCopy(constValue));
7562
+ if (constValue !== void 0) compiledSchema.const = wrapCompiledValue(deepCopy(constValue));
7563
7563
  return wrapCompiledSchema(kind, compiledSchema, context.delegate, context.path);
7564
7564
  }
7565
7565
  //#endregion
@@ -7954,7 +7954,7 @@ function compileSchema(context, schema) {
7954
7954
  let targetSchema = schema;
7955
7955
  let shouldHandleEnumAndConst = false;
7956
7956
  const { enum: enumList, const: constValue } = schema;
7957
- if (enumList || constValue) {
7957
+ if (enumList || constValue !== void 0) {
7958
7958
  const { enum: _0, const: _1, ...rest } = schema;
7959
7959
  targetSchema = rest;
7960
7960
  shouldHandleEnumAndConst = true;
@@ -8544,7 +8544,7 @@ function schemaEqualsChecker(extendsContext) {
8544
8544
  }
8545
8545
  function isValueEquals(value1, value2) {
8546
8546
  if (value1 === value2) return true;
8547
- if (value1 === null) return false;
8547
+ if (value1 === null || value2 === null) return false;
8548
8548
  if (typeof value1 !== "object") return false;
8549
8549
  if (typeof value1 !== typeof value2) return false;
8550
8550
  if (isCompiledSchema(value1) && isCompiledSchema(value2)) return isCompiledSchemaEquals(value1, value2);
@@ -9110,7 +9110,7 @@ function findMismatchPath(source, target) {
9110
9110
  if ((sourceSchema.maxProperties ?? Number.POSITIVE_INFINITY) > (targetSchema.maxProperties ?? Number.POSITIVE_INFINITY)) return [...targetPath, "maxProperties"];
9111
9111
  break;
9112
9112
  }
9113
- case CompiledKind.EnumOrConst: return [...targetPath, targetSchema.const == null ? "enum" : "const"];
9113
+ case CompiledKind.EnumOrConst: return [...targetPath, targetSchema.const === void 0 ? "enum" : "const"];
9114
9114
  }
9115
9115
  return targetPath;
9116
9116
  }
@@ -9610,7 +9610,8 @@ var managedFields = object({
9610
9610
  object({
9611
9611
  kind: literal("connector"),
9612
9612
  action: text,
9613
- connectionId: text.optional()
9613
+ connectionId: text.optional(),
9614
+ outputMode: literal("value").optional()
9614
9615
  }),
9615
9616
  object({
9616
9617
  kind: literal("openapi"),
@@ -10589,6 +10590,285 @@ function nodeOutputPorts(node) {
10589
10590
  }
10590
10591
  }
10591
10592
  //#endregion
10593
+ //#region src/execution/common/dependencies.ts
10594
+ var outputsSchema = record$1(string(), json$1());
10595
+ var inputSchema = record$1(string(), strictObject({
10596
+ execution: number().int().nonnegative(),
10597
+ outputs: outputsSchema
10598
+ }));
10599
+ function dependencyValues(input) {
10600
+ return Object.fromEntries(Object.entries(input).map(([id, result]) => [id, result.outputs]));
10601
+ }
10602
+ var stateSchema = strictObject({
10603
+ id: number().int().nonnegative(),
10604
+ status: _enum([
10605
+ "pending",
10606
+ "running",
10607
+ "completed",
10608
+ "skipped"
10609
+ ]),
10610
+ input: inputSchema,
10611
+ output: outputsSchema.optional(),
10612
+ previous: array(string()),
10613
+ released: array(string()),
10614
+ jobId: string().optional(),
10615
+ seeded: boolean()
10616
+ });
10617
+ var dependenciesSchema = strictObject({
10618
+ nextId: number().int().nonnegative(),
10619
+ iterations: record$1(string(), number().int().nonnegative()),
10620
+ nodes: record$1(string(), stateSchema)
10621
+ });
10622
+ /** Dependency completion belongs to an invocation, never to a Run-wide latest-result table. */
10623
+ var Dependencies = class {
10624
+ constructor(graph, saved) {
10625
+ this.forward = [];
10626
+ this.loops = /* @__PURE__ */ new Map();
10627
+ this.outgoing = /* @__PURE__ */ new Map();
10628
+ this.incoming = /* @__PURE__ */ new Map();
10629
+ this.graph = graph;
10630
+ const feedback = /* @__PURE__ */ new Map();
10631
+ const visited = /* @__PURE__ */ new Set();
10632
+ const stack = /* @__PURE__ */ new Set();
10633
+ const outgoing = /* @__PURE__ */ new Map();
10634
+ for (const edge of graph.edges) {
10635
+ const edges = outgoing.get(edge.source) ?? [];
10636
+ edges.push(edge);
10637
+ outgoing.set(edge.source, edges);
10638
+ }
10639
+ for (const edges of outgoing.values()) edges.sort((a, b) => a.target.localeCompare(b.target) || (a.sourceHandle ?? "").localeCompare(b.sourceHandle ?? ""));
10640
+ const visit = (id) => {
10641
+ if (visited.has(id)) return;
10642
+ visited.add(id);
10643
+ stack.add(id);
10644
+ for (const edge of outgoing.get(id) ?? []) if (stack.has(edge.target)) {
10645
+ const edges = feedback.get(edge.target) ?? [];
10646
+ edges.push(edge);
10647
+ feedback.set(edge.target, edges);
10648
+ } else {
10649
+ this.forward.push(edge);
10650
+ visit(edge.target);
10651
+ }
10652
+ stack.delete(id);
10653
+ };
10654
+ const ids = Object.keys(graph.nodes).toSorted();
10655
+ for (const triggerId of ids.filter((id) => !("inputs" in graph.nodes[id]))) visit(triggerId);
10656
+ for (const id of ids) visit(id);
10657
+ for (const edge of this.forward) {
10658
+ const edges = this.incoming.get(edge.target) ?? [];
10659
+ edges.push(edge);
10660
+ this.incoming.set(edge.target, edges);
10661
+ const children = this.outgoing.get(edge.source) ?? [];
10662
+ children.push(edge);
10663
+ this.outgoing.set(edge.source, children);
10664
+ }
10665
+ for (const [header, edges] of feedback) {
10666
+ const descendants = /* @__PURE__ */ new Set([header]);
10667
+ const walk = (id) => {
10668
+ for (const edge of this.outgoing.get(id) ?? []) {
10669
+ if (descendants.has(edge.target)) continue;
10670
+ descendants.add(edge.target);
10671
+ walk(edge.target);
10672
+ }
10673
+ };
10674
+ walk(header);
10675
+ const body = /* @__PURE__ */ new Set([header]);
10676
+ const backwards = (id) => {
10677
+ if (!descendants.has(id) || body.has(id)) return;
10678
+ body.add(id);
10679
+ for (const edge of this.incoming.get(id) ?? []) backwards(edge.source);
10680
+ };
10681
+ for (const edge of edges) backwards(edge.source);
10682
+ this.loops.set(header, {
10683
+ header,
10684
+ feedback: edges,
10685
+ body,
10686
+ continuation: descendants
10687
+ });
10688
+ }
10689
+ this.innerLoopsFirst = [...this.loops.values()].toSorted((a, b) => a.body.size - b.body.size || a.header.localeCompare(b.header));
10690
+ this.state = saved == null ? {
10691
+ nextId: 0,
10692
+ iterations: {},
10693
+ nodes: {}
10694
+ } : structuredClone(saved);
10695
+ if (saved == null) for (const id of ids) this.state.nodes[id] = this.fresh();
10696
+ else this.validate();
10697
+ }
10698
+ fresh() {
10699
+ return {
10700
+ id: this.state.nextId++,
10701
+ status: "pending",
10702
+ input: {},
10703
+ previous: [],
10704
+ released: [],
10705
+ seeded: false
10706
+ };
10707
+ }
10708
+ validate() {
10709
+ const { nodes, nextId, iterations } = this.state;
10710
+ if (Object.keys(nodes).length != Object.keys(this.graph.nodes).length) throw new Error("Checkpoint dependency nodes do not match the graph.");
10711
+ const ids = /* @__PURE__ */ new Set();
10712
+ for (const [id, state] of Object.entries(nodes)) {
10713
+ if (this.graph.nodes[id] == null || state.id >= nextId || ids.has(state.id)) throw new Error("Checkpoint dependency identity is invalid.");
10714
+ ids.add(state.id);
10715
+ if (state.status == "running" && state.jobId == null) throw new Error("Checkpoint running dependency has no job.");
10716
+ if ((state.status == "pending" || state.status == "skipped") && (state.jobId != null || state.output != null || state.released.length != 0)) throw new Error("Checkpoint inactive dependency contains an execution.");
10717
+ if (state.status == "skipped" && (state.seeded || state.previous.length != 0 || Object.keys(state.input).length != 0)) throw new Error("Checkpoint skipped dependency contains values.");
10718
+ if (state.seeded && (!this.loops.has(id) || state.previous.some((source) => !this.loops.get(id).feedback.some((edge) => edge.source == source)))) throw new Error("Checkpoint recurrence seed is invalid.");
10719
+ if (state.released.length != new Set(state.released).size) throw new Error("Checkpoint released handles are duplicated.");
10720
+ if (state.previous.some((source) => !this.graph.edges.some((edge) => edge.source == source && edge.target == id))) throw new Error("Checkpoint predecessor does not match the graph.");
10721
+ if (state.previous.length != new Set(state.previous).size) throw new Error("Checkpoint predecessors are duplicated.");
10722
+ if (state.status == "completed" && state.output == null) throw new Error("Checkpoint completed dependency has no output.");
10723
+ if (state.previous.some((source) => state.input[source] == null)) throw new Error("Checkpoint predecessor has no input snapshot.");
10724
+ for (const [source, result] of Object.entries(state.input)) if (nodes[source] == null || result.execution > nodes[source].id || result.execution >= nextId) throw new Error("Checkpoint dependency result identity is invalid.");
10725
+ }
10726
+ if (Object.keys(iterations).some((id) => !this.loops.has(id))) throw new Error("Checkpoint loop scope is invalid.");
10727
+ }
10728
+ start(nodeId, outputs) {
10729
+ for (const [id, node] of Object.entries(this.graph.nodes)) {
10730
+ if ("inputs" in node) continue;
10731
+ const state = this.state.nodes[id];
10732
+ state.status = id == nodeId ? "completed" : "skipped";
10733
+ if (id == nodeId) {
10734
+ state.output = outputs;
10735
+ state.released = Object.keys(outputs);
10736
+ }
10737
+ }
10738
+ }
10739
+ edge(edge) {
10740
+ const source = this.state.nodes[edge.source];
10741
+ if (source.status == "skipped") return "skipped";
10742
+ if (edge.sourceHandle != null && source.released.includes(edge.sourceHandle)) return "selected";
10743
+ if (source.status != "completed") return "pending";
10744
+ return edge.sourceHandle == null ? "selected" : "skipped";
10745
+ }
10746
+ collectInputs(edges) {
10747
+ const input = {};
10748
+ const merge = (id, result) => {
10749
+ const previous = input[id];
10750
+ if (previous == null || result.execution > previous.execution) input[id] = result;
10751
+ else if (result.execution == previous.execution) input[id] = {
10752
+ execution: result.execution,
10753
+ outputs: {
10754
+ ...previous.outputs,
10755
+ ...result.outputs
10756
+ }
10757
+ };
10758
+ };
10759
+ for (const edge of edges) {
10760
+ const source = this.state.nodes[edge.source];
10761
+ for (const [id, result] of Object.entries(source.input)) merge(id, result);
10762
+ const outputs = edge.sourceHandle != null && this.graph.nodes[edge.source].kind != "condition" ? Object.fromEntries(Object.entries(source.output).filter(([handle]) => handle == edge.sourceHandle)) : source.output;
10763
+ merge(edge.source, {
10764
+ execution: source.id,
10765
+ outputs
10766
+ });
10767
+ }
10768
+ for (const id of Object.keys(input)) if (this.state.nodes[id].status == "skipped") delete input[id];
10769
+ return input;
10770
+ }
10771
+ inputValues(nodeId) {
10772
+ return dependencyValues(this.state.nodes[nodeId].input);
10773
+ }
10774
+ loopSettled(loop) {
10775
+ return [...loop.body].every((id) => {
10776
+ const state = this.state.nodes[id];
10777
+ return state.status == "completed" || state.status == "skipped";
10778
+ });
10779
+ }
10780
+ blockedByLoop(edge) {
10781
+ if (this.edge(edge) == "selected") return false;
10782
+ for (const loop of this.loops.values()) {
10783
+ const { body } = loop;
10784
+ if (!body.has(edge.source) || body.has(edge.target)) continue;
10785
+ if (!this.loopSettled(loop)) return true;
10786
+ if (loop.feedback.some((back) => this.edge(back) == "selected")) return true;
10787
+ }
10788
+ return false;
10789
+ }
10790
+ continuationPending(loop) {
10791
+ const { body } = loop;
10792
+ const exitBlocked = /* @__PURE__ */ new Map();
10793
+ const awaitsExit = (id) => {
10794
+ if (exitBlocked.has(id)) return exitBlocked.get(id);
10795
+ const blocked = (this.incoming.get(id) ?? []).some((edge) => this.edge(edge) != "selected" && (body.has(edge.source) && !body.has(id) && this.blockedByLoop(edge) || this.state.nodes[edge.source].status == "pending" && awaitsExit(edge.source)));
10796
+ exitBlocked.set(id, blocked);
10797
+ return blocked;
10798
+ };
10799
+ const visited = /* @__PURE__ */ new Set();
10800
+ const visit = (id) => {
10801
+ if (visited.has(id) || body.has(id)) return false;
10802
+ visited.add(id);
10803
+ const state = this.state.nodes[id];
10804
+ if (state.status == "running") return true;
10805
+ if (state.status == "pending") return !awaitsExit(id);
10806
+ return (this.outgoing.get(id) ?? []).some((edge) => this.edge(edge) == "selected" && visit(edge.target));
10807
+ };
10808
+ return this.forward.some((edge) => body.has(edge.source) && !body.has(edge.target) && this.edge(edge) == "selected" && visit(edge.target));
10809
+ }
10810
+ selectedIncoming(nodeId) {
10811
+ const edges = this.incoming.get(nodeId) ?? [];
10812
+ if (edges.some((edge) => this.edge(edge) == "pending" || this.blockedByLoop(edge))) return void 0;
10813
+ return edges.filter((edge) => this.edge(edge) == "selected");
10814
+ }
10815
+ /** Resolve skips and iteration boundaries before admitting another invocation. */
10816
+ ready() {
10817
+ let changed = true;
10818
+ while (changed) {
10819
+ changed = false;
10820
+ for (const loop of this.innerLoopsFirst) {
10821
+ const { header, feedback: edges, continuation: affected } = loop;
10822
+ if (!this.loopSettled(loop)) continue;
10823
+ const selected = edges.filter((edge) => this.edge(edge) == "selected");
10824
+ if (selected.length == 0) continue;
10825
+ if (this.continuationPending(loop) || [...affected].some((id) => this.state.nodes[id].status == "running")) continue;
10826
+ const input = this.collectInputs(selected);
10827
+ this.state.iterations[header] = (this.state.iterations[header] ?? 0) + 1;
10828
+ for (const nested of this.loops.keys()) if (nested != header && affected.has(nested)) delete this.state.iterations[nested];
10829
+ for (const id of affected) this.state.nodes[id] = this.fresh();
10830
+ const entry = this.state.nodes[header];
10831
+ entry.input = input;
10832
+ entry.previous = [...new Set(selected.map((edge) => edge.source))].toSorted();
10833
+ entry.seeded = true;
10834
+ changed = true;
10835
+ break;
10836
+ }
10837
+ for (const [id, state] of Object.entries(this.state.nodes)) {
10838
+ if (state.status != "pending" || state.seeded) continue;
10839
+ if (this.selectedIncoming(id)?.length == 0) {
10840
+ state.status = "skipped";
10841
+ changed = true;
10842
+ }
10843
+ }
10844
+ }
10845
+ return Object.entries(this.state.nodes).flatMap(([id, state]) => {
10846
+ if (state.status != "pending") return [];
10847
+ if (state.seeded) return [id];
10848
+ const selected = this.selectedIncoming(id);
10849
+ if (selected == null || selected.length == 0) return [];
10850
+ state.input = this.collectInputs(selected);
10851
+ for (const member of this.loops.get(id)?.body ?? []) delete state.input[member];
10852
+ state.previous = [...new Set(selected.map((edge) => edge.source))].toSorted();
10853
+ return [id];
10854
+ });
10855
+ }
10856
+ begin(nodeId, jobId) {
10857
+ const state = this.state.nodes[nodeId];
10858
+ state.status = "running";
10859
+ state.jobId = jobId;
10860
+ }
10861
+ release(nodeId, outputs, handles, complete) {
10862
+ const state = this.state.nodes[nodeId];
10863
+ state.output = outputs;
10864
+ state.released = [.../* @__PURE__ */ new Set([...state.released, ...handles])];
10865
+ if (complete) state.status = "completed";
10866
+ }
10867
+ get incomplete() {
10868
+ return Object.values(this.state.nodes).some((state) => state.status == "pending" || state.status == "running");
10869
+ }
10870
+ };
10871
+ //#endregion
10592
10872
  //#region src/execution/common/wait.ts
10593
10873
  /** Shared by decision entry points, the editor, and durable decision storage. */
10594
10874
  var waitCommentSchema = string().trim().refine((value) => [...value].length <= 2e3, "Wait comment must contain at most 2,000 Unicode code points.").nullable().optional();
@@ -10598,6 +10878,7 @@ function normalizeWaitComment$1(value) {
10598
10878
  //#endregion
10599
10879
  //#region src/execution/common/scheduler.ts
10600
10880
  var normalizeWaitComment = normalizeWaitComment$1;
10881
+ var PortValidationError = class extends Error {};
10601
10882
  function usesPending(graph, nodeId) {
10602
10883
  return graph.edges.some((edge) => edge.source == nodeId && edge.sourceHandle == "pending") || Object.values(graph.nodes).some((node) => "inputs" in node && Object.values(node.inputs).some((mapping) => mapping.kind == "sources" && mapping.sources.some((source) => source.kind == "node" && source.nodeId == nodeId && source.output == "pending")));
10603
10884
  }
@@ -10672,7 +10953,7 @@ function decodeFlowRunCheckpoint(input) {
10672
10953
  "agents",
10673
10954
  "bindingValues",
10674
10955
  "counts",
10675
- "frames",
10956
+ "dependencies",
10676
10957
  "inputs",
10677
10958
  "results",
10678
10959
  "version",
@@ -10693,23 +10974,14 @@ function decodeFlowRunCheckpoint(input) {
10693
10974
  }];
10694
10975
  }));
10695
10976
  const counts = record$1(string(), record$1(string(), number().int().positive().max(Number.MAX_SAFE_INTEGER))).parse(source.counts);
10696
- const frames = record$1(string(), record$1(string(), record$1(string(), json$1()))).parse(source.frames);
10697
- const savedWaitFields = {
10977
+ const dependencies = dependenciesSchema.parse(source.dependencies);
10978
+ const pendingWaits = array(strictObject({
10698
10979
  jobId: string().min(1),
10699
10980
  nodeId: string().min(1),
10700
10981
  value: json$1(),
10701
- waitId: string().min(1)
10702
- };
10703
- const pendingWaits = array(union([strictObject({
10704
- ...savedWaitFields,
10982
+ waitId: string().min(1),
10705
10983
  pending: json$1().optional()
10706
- }), strictObject({
10707
- ...savedWaitFields,
10708
- notification: json$1().optional()
10709
- }).transform(({ notification, ...wait }) => ({
10710
- ...wait,
10711
- pending: notification
10712
- }))])).min(1).parse(source.waits);
10984
+ })).min(1).parse(source.waits);
10713
10985
  const agents = record$1(string(), strictObject({
10714
10986
  invocationId: string().min(1),
10715
10987
  input: record$1(string(), json$1()),
@@ -10719,17 +10991,17 @@ function decodeFlowRunCheckpoint(input) {
10719
10991
  const jobs = /* @__PURE__ */ new Set();
10720
10992
  const waits = /* @__PURE__ */ new Set();
10721
10993
  for (const pending of pendingWaits) {
10722
- if (jobs.has(pending.jobId) || waits.has(pending.waitId) || frames[pending.jobId] == null || Object.values(results).some((result) => result.jobId == pending.jobId)) throw new Error("Checkpoint waiting execution states conflict.");
10994
+ if (jobs.has(pending.jobId) || waits.has(pending.waitId) || dependencies.nodes[pending.nodeId]?.status != "running" || dependencies.nodes[pending.nodeId]?.jobId != pending.jobId || Object.values(results).some((result) => result.jobId == pending.jobId)) throw new Error("Checkpoint waiting execution states conflict.");
10723
10995
  jobs.add(pending.jobId);
10724
10996
  waits.add(pending.waitId);
10725
10997
  }
10726
- if (Object.keys(frames).some((id) => !jobs.has(id))) throw new Error("Checkpoint frame has no waiting execution.");
10998
+ if (Object.values(dependencies.nodes).some((state) => state.status == "running" && !jobs.has(state.jobId))) throw new Error("Checkpoint dependency has no waiting execution.");
10727
10999
  if (Object.keys(agents).some((id) => !jobs.has(id))) throw new Error("Checkpoint Agent has no waiting execution.");
10728
11000
  return {
10729
11001
  agents,
10730
11002
  bindingValues,
10731
11003
  counts,
10732
- frames,
11004
+ dependencies,
10733
11005
  inputs,
10734
11006
  results,
10735
11007
  version: 5,
@@ -10797,9 +11069,9 @@ function validateOutputs(nodeId, node, value) {
10797
11069
  const port = ports[handle];
10798
11070
  if (port == null) {
10799
11071
  if (discardUndeclared) continue;
10800
- throw new Error(`Node "${nodeId}" output "${handle}" does not match its declaration.`);
11072
+ throw new PortValidationError(`Node "${nodeId}" output "${handle}" does not match its declaration.`);
10801
11073
  }
10802
- if (!(output === null && port.nullable) && !matchesSchema(output, port.jsonSchema)) throw new Error(`Node "${nodeId}" output "${handle}" does not match its declaration.`);
11074
+ if (!(output === null && port.nullable) && !matchesSchema(output, port.jsonSchema)) throw new PortValidationError(`Node "${nodeId}" output "${handle}" does not match its declaration.`);
10803
11075
  validated[handle] = output;
10804
11076
  }
10805
11077
  return validated;
@@ -10833,11 +11105,6 @@ function validateCheckpoint(target, checkpoint, resolveInputs) {
10833
11105
  validateResults(Object.fromEntries(Object.entries(checkpoint.results).map(([id, result]) => [id, result.outputs])));
10834
11106
  const triggerIds = Object.keys(checkpoint.results).filter((id) => !("inputs" in target.graph.nodes[id]));
10835
11107
  if (triggerIds.length != 1) throw new Error("Checkpoint must contain exactly one selected Trigger.");
10836
- for (const frame of Object.values(checkpoint.frames)) {
10837
- validateResults(frame, true);
10838
- const triggers = Object.keys(frame).filter((id) => !("inputs" in target.graph.nodes[id]));
10839
- if (triggers.length != 1 || triggers[0] != triggerIds[0] || !jsonEqual(frame[triggers[0]], checkpoint.results[triggers[0]].outputs)) throw new Error("Checkpoint frame Trigger does not match the Run.");
10840
- }
10841
11108
  const pendingCounts = /* @__PURE__ */ new Map();
10842
11109
  for (const waiting of checkpoint.waits) pendingCounts.set(waiting.nodeId, (pendingCounts.get(waiting.nodeId) ?? 0) + 1);
10843
11110
  for (const [id, count] of pendingCounts) if ((checkpoint.counts[""]?.[id] ?? 0) < count + (checkpoint.results[id] == null ? 0 : 1)) throw new Error("Checkpoint waiting execution count is incomplete.");
@@ -10845,9 +11112,25 @@ function validateCheckpoint(target, checkpoint, resolveInputs) {
10845
11112
  const node = target.graph.nodes[id];
10846
11113
  if (!("inputs" in node) || Object.keys(values).some((handle) => nodePorts(node)[handle] == null)) throw new Error("Checkpoint launch inputs do not match the prepared graph.");
10847
11114
  }
11115
+ for (const [nodeId, state] of Object.entries(checkpoint.dependencies.nodes)) {
11116
+ const frame = dependencyValues(state.input);
11117
+ validateResults(frame, true);
11118
+ if ("inputs" in target.graph.nodes[nodeId] && (state.status == "running" || state.status == "completed")) {
11119
+ const triggers = Object.keys(frame).filter((id) => !("inputs" in target.graph.nodes[id]));
11120
+ if (triggers.length != 1 || triggers[0] != triggerIds[0] || !jsonEqual(frame[triggers[0]], checkpoint.results[triggers[0]].outputs)) throw new Error("Checkpoint input Trigger does not match the Run.");
11121
+ }
11122
+ if (state.output != null) validateResults({ [nodeId]: state.output }, state.status == "running");
11123
+ if (state.status == "completed") {
11124
+ const result = checkpoint.results[nodeId];
11125
+ if (result == null || state.jobId != null && state.jobId != result.jobId || !jsonEqual(state.output, result.outputs)) throw new Error("Checkpoint completed dependency conflicts with its result.");
11126
+ }
11127
+ }
10848
11128
  for (const waiting of checkpoint.waits) {
10849
11129
  const node = target.graph.nodes[waiting.nodeId];
10850
11130
  if (node == null || !("inputs" in node)) throw new Error("Checkpoint waiting node is missing.");
11131
+ const state = checkpoint.dependencies.nodes[waiting.nodeId];
11132
+ const expectedOutput = waiting.pending == null ? void 0 : { pending: waiting.pending };
11133
+ if (state.output == null != (expectedOutput == null) || state.output != null && !jsonEqual(state.output, expectedOutput)) throw new Error("Checkpoint waiting dependency output is inconsistent.");
10851
11134
  const config = agentConfig(node);
10852
11135
  const saved = agents[waiting.jobId];
10853
11136
  if (!isResolutionNode(node) && config == null) throw new Error("Checkpoint waiting node cannot suspend.");
@@ -10856,10 +11139,10 @@ function validateCheckpoint(target, checkpoint, resolveInputs) {
10856
11139
  if (saved == null || node.timeoutMs == null != (saved.remainingMs == null) || saved.remainingMs != null && saved.remainingMs > node.timeoutMs) throw new Error("Checkpoint Agent budget is invalid.");
10857
11140
  const approval = agentApproval(config, saved.checkpoint, saved.input);
10858
11141
  if (!jsonEqual(waiting.value, approval)) throw new Error("Checkpoint Agent approval does not match its saved call.");
10859
- if (!jsonEqual(resolveInputs(waiting.nodeId, node, waiting.jobId), saved.input)) throw new Error("Checkpoint Agent inputs changed.");
11142
+ if (!jsonEqual(resolveInputs(waiting.nodeId, node), saved.input)) throw new Error("Checkpoint Agent inputs changed.");
10860
11143
  } else {
10861
11144
  if (saved != null) throw new Error("Checkpoint Wait contains Agent state.");
10862
- if (!isResolutionNode(node) || !jsonEqual(resolveInputs(waiting.nodeId, node, waiting.jobId), waiting.value)) throw new Error("Checkpoint resolution input changed.");
11145
+ if (!isResolutionNode(node) || !jsonEqual(resolveInputs(waiting.nodeId, node), waiting.value)) throw new Error("Checkpoint resolution input changed.");
10863
11146
  if (usesPending(target.graph, waiting.nodeId) != (waiting.pending != null)) throw new Error("Checkpoint Wait pending output is missing or unexpected.");
10864
11147
  if (waiting.pending != null) validateOutputs(waiting.nodeId, node, { pending: waiting.pending });
10865
11148
  }
@@ -10883,7 +11166,7 @@ function runGraph(context, target, runId, launchInputs = {}, trigger, resume) {
10883
11166
  const resultNodes = order.filter((id) => !outgoing.has(id)).toSorted();
10884
11167
  const completed = new Map(Object.entries(resume?.checkpoint.results ?? {}));
10885
11168
  const counts = context.counts[""] ??= {};
10886
- const frames = { ...resume?.checkpoint.frames };
11169
+ const dependencies = new Dependencies(target.graph, resume?.checkpoint.dependencies);
10887
11170
  const launch = resume?.checkpoint.inputs ?? launchInputs;
10888
11171
  if (resume == null) {
10889
11172
  if (trigger != null) {
@@ -10925,12 +11208,13 @@ function runGraph(context, target, runId, launchInputs = {}, trigger, resume) {
10925
11208
  }
10926
11209
  if (required && value === void 0) throw new Error(`${description} is incomplete.`);
10927
11210
  if (value === void 0) value = null;
10928
- if (!(value === null && port.nullable) && !matchesSchema(value, port.jsonSchema)) throw new Error(`${description} does not match its declared schema.`);
11211
+ if (!(value === null && port.nullable) && !matchesSchema(value, port.jsonSchema)) throw new PortValidationError(`${description} does not match its declared schema.`);
10929
11212
  return value;
10930
11213
  };
10931
- const resolveInputs = (nodeId, node, jobId) => {
11214
+ const resolveInputs = (nodeId, node) => {
10932
11215
  const mappings = nodeInputMappings(node);
10933
- return Object.fromEntries(Object.entries(nodePorts(node)).map(([handle, port]) => [handle, resolveInput(mappings[handle], port, launch[nodeId]?.[handle], `Node "${nodeId}" input "${handle}"`, frames[jobId], node.kind == "condition")]));
11216
+ const frame = dependencies.inputValues(nodeId);
11217
+ return Object.fromEntries(Object.entries(nodePorts(node)).map(([handle, port]) => [handle, resolveInput(mappings[handle], port, launch[nodeId]?.[handle], `Node "${nodeId}" input "${handle}"`, frame, node.kind == "condition")]));
10934
11218
  };
10935
11219
  const commit = (nodeId, jobId, outputs, releasedHandles = Object.keys(outputs)) => Effect.uninterruptible(Effect.gen(function* () {
10936
11220
  yield* context.emit({
@@ -10944,25 +11228,9 @@ function runGraph(context, target, runId, launchInputs = {}, trigger, resume) {
10944
11228
  jobId,
10945
11229
  outputs
10946
11230
  });
10947
- const frame = {
10948
- ...frames[jobId],
10949
- [nodeId]: outputs
10950
- };
10951
- delete frames[jobId];
10952
- dispatch(nodeId, releasedHandles, frame);
11231
+ dependencies.release(nodeId, outputs, releasedHandles, true);
10953
11232
  }));
10954
- const ready = [];
10955
- const scheduleReady = (nodeId, frame, previousId) => {
10956
- ready.push({
10957
- nodeId,
10958
- frame,
10959
- previousId
10960
- });
10961
- };
10962
- const dispatch = (nodeId, releasedHandles, frame) => {
10963
- for (const edge of outgoing.get(nodeId) ?? []) if (edge.sourceHandle == null || releasedHandles.includes(edge.sourceHandle)) scheduleReady(edge.target, frame, nodeId);
10964
- };
10965
- const executeNode = (nodeId, node, jobId, nodeInputs, resolution, previousId) => {
11233
+ const executeNode = (nodeId, node, jobId, nodeInputs, resolution) => {
10966
11234
  const config = agentConfig(node);
10967
11235
  const saved = agents[jobId];
10968
11236
  const nodeRemainingMs = saved?.remainingMs ?? node.timeoutMs;
@@ -10995,7 +11263,8 @@ function runGraph(context, target, runId, launchInputs = {}, trigger, resume) {
10995
11263
  outputs = Object.fromEntries(node.values.map((port) => [port.handle, port.value ?? null]));
10996
11264
  break;
10997
11265
  case "task": {
10998
- const frame = frames[jobId];
11266
+ const frame = dependencies.inputValues(nodeId);
11267
+ const previousIds = dependencies.state.nodes[nodeId].previous;
10999
11268
  const additional = new Set((node.additionalInputs ?? []).map((port) => port.handle));
11000
11269
  const result = yield* context.invokeTask({
11001
11270
  additionalInputs: Object.fromEntries(Object.entries(nodeInputs).filter(([handle]) => additional.has(handle))),
@@ -11020,18 +11289,19 @@ function runGraph(context, target, runId, launchInputs = {}, trigger, resume) {
11020
11289
  capabilities: node.task.capabilities ?? [],
11021
11290
  moduleId: node.task.moduleId,
11022
11291
  getPrevious: () => {
11023
- if (previousId == null) return null;
11024
- const previous = target.graph.nodes[previousId];
11025
- return {
11026
- id: previousId,
11027
- name: previous.name ?? ("inputs" in previous ? nodeTitle(previous) : void 0) ?? previousId,
11028
- outputs: frame[previousId],
11029
- outputDefs: Object.entries(nodeOutputPorts(previous)).map(([handle, definition]) => Object.assign({
11030
- handle,
11031
- jsonSchema: definition.jsonSchema,
11032
- nullable: definition.nullable
11033
- }, definition.description == null ? {} : { description: definition.description }))
11034
- };
11292
+ return previousIds.map((previousId) => {
11293
+ const previous = target.graph.nodes[previousId];
11294
+ return {
11295
+ id: previousId,
11296
+ name: previous.name ?? ("inputs" in previous ? nodeTitle(previous) : void 0) ?? previousId,
11297
+ outputs: frame[previousId],
11298
+ outputDefs: Object.entries(nodeOutputPorts(previous)).map(([handle, definition]) => Object.assign({
11299
+ handle,
11300
+ jsonSchema: definition.jsonSchema,
11301
+ nullable: definition.nullable
11302
+ }, definition.description == null ? {} : { description: definition.description }))
11303
+ };
11304
+ });
11035
11305
  }
11036
11306
  } : { kind: "managed" }
11037
11307
  });
@@ -11054,7 +11324,8 @@ function runGraph(context, target, runId, launchInputs = {}, trigger, resume) {
11054
11324
  };
11055
11325
  }
11056
11326
  outputs = { output: response.output };
11057
- } else outputs = outputRecord(result, nodeId);
11327
+ } else if ("executor" in node.task && node.task.executor.kind == "connector" && node.task.executor.outputMode == "value") outputs = { output: checkpointJson(result, `Node "${nodeId}" output`) };
11328
+ else outputs = outputRecord(result, nodeId);
11058
11329
  break;
11059
11330
  }
11060
11331
  case "approval":
@@ -11090,11 +11361,7 @@ function runGraph(context, target, runId, launchInputs = {}, trigger, resume) {
11090
11361
  });
11091
11362
  if (notify) {
11092
11363
  validateOutputs(nodeId, node, { pending });
11093
- const frame = {
11094
- ...frames[jobId],
11095
- [nodeId]: { pending }
11096
- };
11097
- dispatch(nodeId, ["pending"], frame);
11364
+ dependencies.release(nodeId, { pending }, ["pending"], false);
11098
11365
  }
11099
11366
  pendingWaits.set(jobId, {
11100
11367
  jobId,
@@ -11130,7 +11397,7 @@ function runGraph(context, target, runId, launchInputs = {}, trigger, resume) {
11130
11397
  })), Effect.tapCause((cause) => Effect.sync(() => {
11131
11398
  firstCause ??= cause;
11132
11399
  })));
11133
- const executeReady = (nodeId, frame, previousId) => {
11400
+ const executeReady = (nodeId) => {
11134
11401
  if (firstCause != null) return;
11135
11402
  const node = target.graph.nodes[nodeId];
11136
11403
  if (!("inputs" in node)) return;
@@ -11142,10 +11409,10 @@ function runGraph(context, target, runId, launchInputs = {}, trigger, resume) {
11142
11409
  return;
11143
11410
  }
11144
11411
  counts[nodeId] = count + 1;
11145
- frames[jobId] = frame;
11412
+ dependencies.begin(nodeId, jobId);
11146
11413
  runNode(observe(nodeId, jobId, Effect.gen(function* () {
11147
11414
  const nodeInputs = yield* Effect.try({
11148
- try: () => resolveInputs(nodeId, node, jobId),
11415
+ try: () => resolveInputs(nodeId, node),
11149
11416
  catch: (error) => error instanceof Error ? error : new Error(String(error))
11150
11417
  });
11151
11418
  if (isResolutionNode(node)) {
@@ -11164,7 +11431,7 @@ function runGraph(context, target, runId, launchInputs = {}, trigger, resume) {
11164
11431
  yield* createWait(nodeId, jobId, nodeInputs);
11165
11432
  return;
11166
11433
  }
11167
- const result = yield* executeNode(nodeId, node, jobId, nodeInputs, void 0, previousId);
11434
+ const result = yield* executeNode(nodeId, node, jobId, nodeInputs);
11168
11435
  yield* settleNode(nodeId, jobId, result);
11169
11436
  })).pipe(Effect.ensuring(Queue.offer(changes, void 0))));
11170
11437
  };
@@ -11173,7 +11440,7 @@ function runGraph(context, target, runId, launchInputs = {}, trigger, resume) {
11173
11440
  catch: (error) => error instanceof Error ? error : new Error(String(error))
11174
11441
  });
11175
11442
  if (resume == null) {
11176
- if (trigger != null) dispatch(trigger.nodeId, Object.keys(trigger.outputs), { [trigger.nodeId]: trigger.outputs });
11443
+ if (trigger != null) dependencies.start(trigger.nodeId, trigger.outputs);
11177
11444
  }
11178
11445
  const applyResolutions = (resolutions, now) => {
11179
11446
  for (const saved of pendingWaits.values()) {
@@ -11221,10 +11488,14 @@ function runGraph(context, target, runId, launchInputs = {}, trigger, resume) {
11221
11488
  return yield* Effect.failCause(firstCause);
11222
11489
  }
11223
11490
  if (pendingWaits.size > 0 && context.waits != null) applyResolutions(yield* context.waits.resolutions([...pendingWaits.values()].map((wait) => wait.waitId), false), now);
11224
- for (const arrival of ready.splice(0)) executeReady(arrival.nodeId, arrival.frame, arrival.previousId);
11491
+ const ready = dependencies.ready();
11492
+ for (const nodeId of ready) executeReady(nodeId);
11225
11493
  const running = yield* FiberSet.size(active);
11226
11494
  if (firstCause != null) continue;
11227
- if (running == 0 && pendingWaits.size == 0 && ready.length == 0) break;
11495
+ if (running == 0 && pendingWaits.size == 0 && ready.length == 0) {
11496
+ if (dependencies.incomplete) return yield* Effect.fail(/* @__PURE__ */ new Error("Execution graph contains unresolved dependencies."));
11497
+ break;
11498
+ }
11228
11499
  if (running > 0 || ready.length > 0) idleSince = void 0;
11229
11500
  else idleSince ??= now;
11230
11501
  const left = idleSince == null ? remainingMs : waitRetentionMs - (now - idleSince);
@@ -11234,7 +11505,7 @@ function runGraph(context, target, runId, launchInputs = {}, trigger, resume) {
11234
11505
  inputs: launch,
11235
11506
  results: Object.fromEntries(completed),
11236
11507
  counts: context.counts,
11237
- frames,
11508
+ dependencies: dependencies.state,
11238
11509
  version: 5,
11239
11510
  agents,
11240
11511
  waits: [...pendingWaits.values()]
@@ -11305,4 +11576,4 @@ function runFlow(prepared, options) {
11305
11576
  });
11306
11577
  }
11307
11578
  //#endregion
11308
- export { decodeFlowRunCheckpoint, normalizeWaitComment, runFlow, waitRetentionMs };
11579
+ export { PortValidationError, decodeFlowRunCheckpoint, normalizeWaitComment, runFlow, waitRetentionMs };
@@ -1,4 +1,6 @@
1
1
  import type { Group, InputPort, InputValues, JsonValue } from '../browser/flow-change.js';
2
+ /** Deployment-bound selections owned by the Trigger configuration contract. */
3
+ export declare function clearTriggerExternalConfig(key: string, config: InputValues): InputValues;
2
4
  export declare function triggerConfigValue(input: InputPort, config: InputValues): JsonValue | undefined;
3
5
  /** Provider-specific controls consume values, never persistence wrappers. */
4
6
  export declare function triggerConfigValues(inputs: readonly (InputPort | Group)[], config: InputValues): Readonly<Record<string, JsonValue>>;