@fluidgrids/workflows 2026.1027.0 → 2026.1027.1

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 (52) hide show
  1. package/README.md +26 -5
  2. package/dist/{assemble-DMOuaxRI.d.ts → assemble-CrpUyd_3.d.ts} +20 -2
  3. package/dist/{assemble-BJo9TECS.d.cts → assemble-DEf3znGD.d.cts} +20 -2
  4. package/dist/chunk-3M34AUIY.cjs +27 -0
  5. package/dist/chunk-5AW745OG.js +25 -0
  6. package/dist/{chunk-RRQ5HOBF.cjs → chunk-6AIAC2FP.cjs} +4 -4
  7. package/dist/{chunk-GO34UHSY.js → chunk-6BEW4QD6.js} +3 -3
  8. package/dist/{chunk-SS4LT2IP.js → chunk-6U446SKY.js} +5 -10
  9. package/dist/{chunk-AU3YW7FZ.cjs → chunk-7YR7DI7B.cjs} +46 -51
  10. package/dist/{chunk-27HASETB.cjs → chunk-CSYBNN3V.cjs} +3 -1
  11. package/dist/{chunk-LRM6JXJA.cjs → chunk-E3APHA6O.cjs} +19 -1
  12. package/dist/{chunk-BWSLWF2E.js → chunk-EEAIM35V.js} +38 -12
  13. package/dist/{chunk-X4HKU3MX.js → chunk-IHKXLG6I.js} +3 -1
  14. package/dist/chunk-MBBKGD7K.js +440 -0
  15. package/dist/{chunk-LSKSBVL4.cjs → chunk-OSPTJCDI.cjs} +6 -6
  16. package/dist/{chunk-KUTMY2IO.cjs → chunk-TQF7MYEN.cjs} +101 -75
  17. package/dist/{chunk-BYJ7QTLY.cjs → chunk-TWOYB4Y7.cjs} +13 -13
  18. package/dist/{chunk-PL73GJR4.js → chunk-UB2BHU2M.js} +1 -1
  19. package/dist/{chunk-REV7ZOA4.js → chunk-UJNHTS6D.js} +13 -2
  20. package/dist/{chunk-IZQNUNSU.cjs → chunk-UWQWD7BP.cjs} +17 -17
  21. package/dist/{chunk-4DPEGDPW.js → chunk-W32BSO3M.js} +4 -4
  22. package/dist/{chunk-LMX35GNQ.js → chunk-XBIID5DY.js} +4 -4
  23. package/dist/chunk-Y7NWR3WH.cjs +450 -0
  24. package/dist/codegen/index.cjs +7 -7
  25. package/dist/codegen/index.js +5 -5
  26. package/dist/index.cjs +30 -30
  27. package/dist/index.d.cts +3 -3
  28. package/dist/index.d.ts +3 -3
  29. package/dist/index.js +3 -3
  30. package/dist/ir/index.cjs +118 -116
  31. package/dist/ir/index.d.cts +18 -8
  32. package/dist/ir/index.d.ts +18 -8
  33. package/dist/ir/index.js +21 -19
  34. package/dist/{lower-Dw5grNrI.d.ts → lower-CXggJTIo.d.ts} +20 -2
  35. package/dist/{lower-DcOY8ux0.d.cts → lower-DAzvsJCo.d.cts} +20 -2
  36. package/dist/node-evaluator-CH3XCJND.cjs +17 -0
  37. package/dist/node-evaluator-TULXA3WE.js +8 -0
  38. package/dist/quickjs/index.cjs +32 -78
  39. package/dist/quickjs/index.d.cts +4 -4
  40. package/dist/quickjs/index.d.ts +4 -4
  41. package/dist/quickjs/index.js +32 -78
  42. package/dist/roundtrip/index.cjs +201 -128
  43. package/dist/roundtrip/index.d.cts +7 -4
  44. package/dist/roundtrip/index.d.ts +7 -4
  45. package/dist/roundtrip/index.js +87 -18
  46. package/package.json +44 -18
  47. package/dist/chunk-265J2FCH.cjs +0 -33
  48. package/dist/chunk-LUXCXFOE.cjs +0 -269
  49. package/dist/chunk-S34NJE3A.js +0 -262
  50. package/dist/chunk-SRQRLWOS.js +0 -31
  51. package/dist/node-evaluator-2GTUZVPK.cjs +0 -17
  52. package/dist/node-evaluator-RMYEWCXZ.js +0 -8
@@ -1,16 +1,16 @@
1
1
  'use strict';
2
2
 
3
- var chunkBYJ7QTLY_cjs = require('../chunk-BYJ7QTLY.cjs');
4
- var chunkIZQNUNSU_cjs = require('../chunk-IZQNUNSU.cjs');
5
- var chunkLSKSBVL4_cjs = require('../chunk-LSKSBVL4.cjs');
6
- var chunk265J2FCH_cjs = require('../chunk-265J2FCH.cjs');
7
- var chunkLUXCXFOE_cjs = require('../chunk-LUXCXFOE.cjs');
8
- var chunkKUTMY2IO_cjs = require('../chunk-KUTMY2IO.cjs');
9
- var chunkAU3YW7FZ_cjs = require('../chunk-AU3YW7FZ.cjs');
3
+ var chunkTWOYB4Y7_cjs = require('../chunk-TWOYB4Y7.cjs');
4
+ var chunkUWQWD7BP_cjs = require('../chunk-UWQWD7BP.cjs');
5
+ var chunkOSPTJCDI_cjs = require('../chunk-OSPTJCDI.cjs');
6
+ var chunk3M34AUIY_cjs = require('../chunk-3M34AUIY.cjs');
7
+ var chunkY7NWR3WH_cjs = require('../chunk-Y7NWR3WH.cjs');
8
+ var chunkTQF7MYEN_cjs = require('../chunk-TQF7MYEN.cjs');
9
+ var chunk7YR7DI7B_cjs = require('../chunk-7YR7DI7B.cjs');
10
10
  require('../chunk-G4UEPUGO.cjs');
11
- var chunkRRQ5HOBF_cjs = require('../chunk-RRQ5HOBF.cjs');
12
- var chunk27HASETB_cjs = require('../chunk-27HASETB.cjs');
13
- var chunkLRM6JXJA_cjs = require('../chunk-LRM6JXJA.cjs');
11
+ var chunk6AIAC2FP_cjs = require('../chunk-6AIAC2FP.cjs');
12
+ var chunkCSYBNN3V_cjs = require('../chunk-CSYBNN3V.cjs');
13
+ var chunkE3APHA6O_cjs = require('../chunk-E3APHA6O.cjs');
14
14
 
15
15
  // src/roundtrip/plan.ts
16
16
  var TYPED_HANDLES = {
@@ -79,14 +79,14 @@ var LiftError = class extends Error {
79
79
  }
80
80
  };
81
81
  var RULE_METHOD_BY_OPERATOR = new Map(
82
- Object.entries(chunkRRQ5HOBF_cjs.PREDICATE_OPERATORS).map(([method, spec]) => [
82
+ Object.entries(chunk6AIAC2FP_cjs.PREDICATE_OPERATORS).map(([method, spec]) => [
83
83
  spec.operator,
84
84
  { method, unary: spec.unary }
85
85
  ])
86
86
  );
87
87
  function literalOrStructure(value2) {
88
88
  if (Array.isArray(value2)) return { k: "array", items: value2.map(literalOrStructure) };
89
- if (chunkLRM6JXJA_cjs.isRecord(value2))
89
+ if (chunkE3APHA6O_cjs.isRecord(value2))
90
90
  return {
91
91
  k: "object",
92
92
  entries: Object.entries(value2).map(([key, child]) => [key, literalOrStructure(child)])
@@ -98,7 +98,7 @@ function literalOrStructure(value2) {
98
98
  }
99
99
  function expressible(ref) {
100
100
  return ref.path.every(
101
- (segment) => segment.kind === "index" || !chunkRRQ5HOBF_cjs.RESERVED_REF_KEYS.has(segment.key)
101
+ (segment) => segment.kind === "index" || !chunk6AIAC2FP_cjs.RESERVED_REF_KEYS.has(segment.key)
102
102
  );
103
103
  }
104
104
  function toPlanRef(ref) {
@@ -107,7 +107,7 @@ function toPlanRef(ref) {
107
107
  }
108
108
  function liftValue(value2, path, nodeId, items) {
109
109
  if (typeof value2 === "string") {
110
- const parts = chunkLRM6JXJA_cjs.parseTemplate(value2);
110
+ const parts = chunkE3APHA6O_cjs.parseTemplate(value2);
111
111
  if (parts && parts.every((part) => part.kind === "text" || expressible(part.ref))) {
112
112
  const [only] = parts;
113
113
  if (parts.length === 1 && only?.kind === "ref") return { k: "ref", ref: toPlanRef(only.ref) };
@@ -136,7 +136,7 @@ function liftValue(value2, path, nodeId, items) {
136
136
  k: "array",
137
137
  items: value2.map((item, index) => liftValue(item, `${path}[${index}]`, nodeId, items))
138
138
  };
139
- if (chunkLRM6JXJA_cjs.isRecord(value2)) {
139
+ if (chunkE3APHA6O_cjs.isRecord(value2)) {
140
140
  return {
141
141
  k: "object",
142
142
  entries: Object.entries(value2).map(([key, child]) => [
@@ -185,7 +185,7 @@ function liftRule(rule, nodeIds) {
185
185
  if (typeof rule["field"] !== "string" || typeof rule["operator"] !== "string" || rule["operator"] === "")
186
186
  return void 0;
187
187
  const ref = fieldRef(rule["field"], nodeIds);
188
- if (!ref || !ref.path.every((segment) => segment.kind === "index" || !chunkRRQ5HOBF_cjs.RESERVED_REF_KEYS.has(segment.key))) {
188
+ if (!ref || !ref.path.every((segment) => segment.kind === "index" || !chunk6AIAC2FP_cjs.RESERVED_REF_KEYS.has(segment.key))) {
189
189
  return void 0;
190
190
  }
191
191
  const hasValue = Object.hasOwn(rule, "value");
@@ -204,7 +204,7 @@ function liftRule(rule, nodeIds) {
204
204
  };
205
205
  }
206
206
  function liftCondition(tree, nodeIds, top) {
207
- if (!chunkLRM6JXJA_cjs.isRecord(tree)) return void 0;
207
+ if (!chunkE3APHA6O_cjs.isRecord(tree)) return void 0;
208
208
  if (tree["type"] === "rule") return top ? void 0 : liftRule(tree, nodeIds);
209
209
  if (tree["type"] !== "group") return void 0;
210
210
  const keys = Object.keys(tree).sort();
@@ -245,7 +245,7 @@ function richEdge(edge2, info, items) {
245
245
  const options2 = [];
246
246
  const extra = [];
247
247
  if (edge2["id"] === void 0) options2.push(["id", { k: "literal", value: false }]);
248
- else if (edge2["id"] !== chunkKUTMY2IO_cjs.defaultEdgeId(source, target, sourceHandle, targetHandle))
248
+ else if (edge2["id"] !== chunkTQF7MYEN_cjs.defaultEdgeId(source, target, sourceHandle, targetHandle))
249
249
  options2.push(["id", literalOrStructure(edge2["id"])]);
250
250
  if (edge2["type"] === void 0) options2.push(["type", { k: "literal", value: false }]);
251
251
  else if (edge2["type"] !== "deletable") options2.push(["type", literalOrStructure(edge2["type"])]);
@@ -259,7 +259,7 @@ function richEdge(edge2, info, items) {
259
259
  }
260
260
  if (key === "label" && typeof value2 === "string")
261
261
  options2.push(["label", { k: "literal", value: value2 }]);
262
- else if ((key === "data" || key === "mapping") && chunkLRM6JXJA_cjs.isRecord(value2)) {
262
+ else if ((key === "data" || key === "mapping") && chunkE3APHA6O_cjs.isRecord(value2)) {
263
263
  options2.push([key, literalOrStructure(value2)]);
264
264
  if (key === "mapping") {
265
265
  items.push({
@@ -312,10 +312,10 @@ function chooseOperation(node, hasIncoming, clients, manifests, items) {
312
312
  const manifest = manifests?.find(
313
313
  (candidate) => candidate.nodeType === type && candidate.nodeVersion === client?.version
314
314
  );
315
- const operation = operationName && manifest ? chunkLSKSBVL4_cjs.operationsOf(manifest).find((candidate) => candidate.name === operationName) : void 0;
315
+ const operation = operationName && manifest ? chunkOSPTJCDI_cjs.operationsOf(manifest).find((candidate) => candidate.name === operationName) : void 0;
316
316
  const operationKey = operationName ? client?.operations.get(operationName) : void 0;
317
317
  if (client && operation && operationKey) {
318
- const isTrigger = chunkLSKSBVL4_cjs.isTriggerOperation(operation);
318
+ const isTrigger = chunkOSPTJCDI_cjs.isTriggerOperation(operation);
319
319
  return {
320
320
  method: isTrigger && !hasIncoming ? "trigger" : "step",
321
321
  operation: {
@@ -352,7 +352,7 @@ function chooseOperation(node, hasIncoming, clients, manifests, items) {
352
352
  }
353
353
  var ERROR_CONFIG_KEYS = /* @__PURE__ */ new Set(["onError", "errorBranchId", "retryConfig", "timeout"]);
354
354
  function errorConfigOptions(errorConfig) {
355
- if (!chunkLRM6JXJA_cjs.isRecord(errorConfig) || Object.keys(errorConfig).length === 0) return void 0;
355
+ if (!chunkE3APHA6O_cjs.isRecord(errorConfig) || Object.keys(errorConfig).length === 0) return void 0;
356
356
  if (!Object.keys(errorConfig).every((key) => ERROR_CONFIG_KEYS.has(key))) return void 0;
357
357
  const options2 = [];
358
358
  const onError = errorConfig["onError"];
@@ -370,23 +370,46 @@ function errorConfigOptions(errorConfig) {
370
370
  else if (onError !== void 0) return void 0;
371
371
  }
372
372
  if (errorConfig["retryConfig"] !== void 0) {
373
- if (!chunkLRM6JXJA_cjs.isRecord(errorConfig["retryConfig"])) return void 0;
373
+ if (!chunkE3APHA6O_cjs.isRecord(errorConfig["retryConfig"])) return void 0;
374
374
  options2.push(["retry", literalOrStructure(errorConfig["retryConfig"])]);
375
375
  }
376
376
  if (errorConfig["timeout"] !== void 0) {
377
- if (!chunkLRM6JXJA_cjs.isRecord(errorConfig["timeout"])) return void 0;
377
+ if (!chunkE3APHA6O_cjs.isRecord(errorConfig["timeout"])) return void 0;
378
378
  options2.push(["timeout", literalOrStructure(errorConfig["timeout"])]);
379
379
  }
380
380
  return options2;
381
381
  }
382
+ function ambiguousConnectionNames(names) {
383
+ const idByName = /* @__PURE__ */ new Map();
384
+ const ambiguous = /* @__PURE__ */ new Set();
385
+ for (const [id, name] of Object.entries(names)) {
386
+ const previous = idByName.get(name);
387
+ if (previous === void 0) idByName.set(name, id);
388
+ else if (previous !== id) ambiguous.add(name);
389
+ }
390
+ return ambiguous;
391
+ }
382
392
  function connectionOptions(value2, names, nodeId, items) {
383
393
  if (Array.isArray(value2) && value2.length > 0 && names) {
394
+ const ambiguous = ambiguousConnectionNames(names);
384
395
  const resolved = value2.map((ref) => {
385
- if (!chunkLRM6JXJA_cjs.isRecord(ref) || Object.keys(ref).sort().join(",") !== "adapter,connectionId")
396
+ if (!chunkE3APHA6O_cjs.isRecord(ref) || Object.keys(ref).sort().join(",") !== "adapter,connectionId")
386
397
  return void 0;
387
398
  const id = ref["connectionId"];
388
399
  return typeof id === "string" && Object.hasOwn(names, id) ? names[id] : void 0;
389
400
  });
401
+ const shared = resolved.filter(
402
+ (name) => typeof name === "string" && ambiguous.has(name)
403
+ );
404
+ if (shared.length > 0) {
405
+ items.push({
406
+ nodeId,
407
+ path: "args.connections",
408
+ kind: "connection-ambiguous",
409
+ detail: `The connection name ${[...new Set(shared)].map((name) => `"${name}"`).join(", ")} belongs to more than one connection; the connection id is kept`
410
+ });
411
+ return ["connections", literalOrStructure(value2)];
412
+ }
390
413
  if (resolved.every((name) => typeof name === "string")) {
391
414
  return resolved.length === 1 ? ["connection", { k: "literal", value: resolved[0] ?? "" }] : [
392
415
  "connection",
@@ -434,12 +457,12 @@ function richNode(node, choice, incoming, nodeIds, options2, items) {
434
457
  extra.push(["version", literalOrStructure(version)]);
435
458
  }
436
459
  }
437
- const args = chunkLRM6JXJA_cjs.isRecord(node["args"]) ? node["args"] : void 0;
460
+ const args = chunkE3APHA6O_cjs.isRecord(node["args"]) ? node["args"] : void 0;
438
461
  if (node["args"] !== void 0 && !args) extra.push(["args", literalOrStructure(node["args"])]);
439
462
  if (args) {
440
463
  const argsExtra = [];
441
464
  let state = args["state"];
442
- if (choice.method === "if" && chunkLRM6JXJA_cjs.isRecord(state) && state["conditionTree"] !== void 0) {
465
+ if (choice.method === "if" && chunkE3APHA6O_cjs.isRecord(state) && state["conditionTree"] !== void 0) {
443
466
  const condition = liftCondition(state["conditionTree"], nodeIds, true);
444
467
  if (condition) {
445
468
  out.push(["condition", condition]);
@@ -449,7 +472,7 @@ function richNode(node, choice, incoming, nodeIds, options2, items) {
449
472
  }
450
473
  }
451
474
  if (state !== void 0) {
452
- if (chunkLRM6JXJA_cjs.isRecord(state)) out.push(["args", liftState(String(node["type"]), state, id, items)]);
475
+ if (chunkE3APHA6O_cjs.isRecord(state)) out.push(["args", liftState(String(node["type"]), state, id, items)]);
453
476
  else argsExtra.push(["state", literalOrStructure(state)]);
454
477
  }
455
478
  for (const [key, value2] of Object.entries(args)) {
@@ -464,7 +487,7 @@ function richNode(node, choice, incoming, nodeIds, options2, items) {
464
487
  kind: "legacy-syntax",
465
488
  detail: "Legacy credential references kept verbatim"
466
489
  });
467
- } else if (key === "context" && chunkLRM6JXJA_cjs.isRecord(value2))
490
+ } else if (key === "context" && chunkE3APHA6O_cjs.isRecord(value2))
468
491
  out.push(["context", literalOrStructure(value2)]);
469
492
  else argsExtra.push([key, literalOrStructure(value2)]);
470
493
  }
@@ -477,12 +500,12 @@ function richNode(node, choice, incoming, nodeIds, options2, items) {
477
500
  if (sugar) out.push(...sugar);
478
501
  else out.push(["errorConfig", literalOrStructure(node["errorConfig"])]);
479
502
  }
480
- const data = chunkLRM6JXJA_cjs.isRecord(node["data"]) ? { ...node["data"] } : void 0;
503
+ const data = chunkE3APHA6O_cjs.isRecord(node["data"]) ? { ...node["data"] } : void 0;
481
504
  if (node["executionSettings"] !== void 0) {
482
505
  const settings = node["executionSettings"];
483
- if (chunkLRM6JXJA_cjs.isRecord(settings)) {
484
- const mirror = chunkLRM6JXJA_cjs.isRecord(data?.["executionSettings"]) ? data["executionSettings"] : void 0;
485
- const mirrored = settings["runOn"] !== void 0 && mirror !== void 0 && Object.keys(mirror).length === 1 && chunkLRM6JXJA_cjs.deepEqual(mirror["runOn"], settings["runOn"]);
506
+ if (chunkE3APHA6O_cjs.isRecord(settings)) {
507
+ const mirror = chunkE3APHA6O_cjs.isRecord(data?.["executionSettings"]) ? data["executionSettings"] : void 0;
508
+ const mirrored = settings["runOn"] !== void 0 && mirror !== void 0 && Object.keys(mirror).length === 1 && chunkE3APHA6O_cjs.deepEqual(mirror["runOn"], settings["runOn"]);
486
509
  if (settings["runOn"] === void 0 || mirrored) {
487
510
  out.push(["executionSettings", literalOrStructure(settings)]);
488
511
  if (mirrored && data) delete data["executionSettings"];
@@ -503,9 +526,9 @@ function richNode(node, choice, incoming, nodeIds, options2, items) {
503
526
  else extra.push(["disabled", literalOrStructure(node["disabled"])]);
504
527
  }
505
528
  if (data && Object.keys(data).length > 0) extra.push(["data", literalOrStructure(data)]);
506
- else if (node["data"] !== void 0 && !chunkLRM6JXJA_cjs.isRecord(node["data"]))
529
+ else if (node["data"] !== void 0 && !chunkE3APHA6O_cjs.isRecord(node["data"]))
507
530
  extra.push(["data", literalOrStructure(node["data"])]);
508
- else if (chunkLRM6JXJA_cjs.isRecord(node["data"]) && Object.keys(node["data"]).length === 0)
531
+ else if (chunkE3APHA6O_cjs.isRecord(node["data"]) && Object.keys(node["data"]).length === 0)
509
532
  extra.push(["data", { k: "object", entries: [] }]);
510
533
  for (const [key, value2] of Object.entries(node)) {
511
534
  if ([
@@ -570,17 +593,17 @@ function workflowOptions(definition, key) {
570
593
  for (const option of WORKFLOW_OPTION_KEYS) {
571
594
  const value2 = definition[option];
572
595
  if (value2 === void 0) continue;
573
- if (option === "meta" && chunkLRM6JXJA_cjs.isRecord(value2)) {
596
+ if (option === "meta" && chunkE3APHA6O_cjs.isRecord(value2)) {
574
597
  const meta = { ...value2 };
575
598
  delete meta["layout"];
576
599
  if (Object.keys(meta).length > 0) out.push(["meta", literalOrStructure(meta)]);
577
600
  continue;
578
601
  }
579
- const typed = (option === "name" || option === "description") && typeof value2 === "string" || option === "tags" && Array.isArray(value2) || ["config", "interface", "code"].includes(option) && chunkLRM6JXJA_cjs.isRecord(value2);
602
+ const typed = (option === "name" || option === "description") && typeof value2 === "string" || option === "tags" && Array.isArray(value2) || ["config", "interface", "code"].includes(option) && chunkE3APHA6O_cjs.isRecord(value2);
580
603
  if (typed) out.push([option, literalOrStructure(value2)]);
581
604
  else extra.push([option, literalOrStructure(value2)]);
582
605
  }
583
- const data = chunkLRM6JXJA_cjs.isRecord(definition["data"]) ? definition["data"] : {};
606
+ const data = chunkE3APHA6O_cjs.isRecord(definition["data"]) ? definition["data"] : {};
584
607
  const dataExtra = Object.entries(data).filter(
585
608
  ([dataKey]) => !["nodes", "edges", "stickyNotes"].includes(dataKey)
586
609
  );
@@ -601,14 +624,14 @@ function workflowOptions(definition, key) {
601
624
  }
602
625
  function buildPlan(normalized, options2, rawNodeIds = /* @__PURE__ */ new Set(), rawEdgeIndices = /* @__PURE__ */ new Set()) {
603
626
  const items = [];
604
- const data = chunkLRM6JXJA_cjs.isRecord(normalized["data"]) ? normalized["data"] : {};
627
+ const data = chunkE3APHA6O_cjs.isRecord(normalized["data"]) ? normalized["data"] : {};
605
628
  const nodes2 = Array.isArray(data["nodes"]) ? data["nodes"] : [];
606
629
  const edges = Array.isArray(data["edges"]) ? data["edges"] : [];
607
630
  const key = typeof normalized["key"] === "string" && normalized["key"] ? normalized["key"] : options2.workflowKey;
608
631
  if (!key) throw new LiftError("The definition has no key; pass workflowKey");
609
632
  const nodeIds = /* @__PURE__ */ new Set();
610
633
  for (const node of nodes2) {
611
- if (!chunkLRM6JXJA_cjs.isRecord(node) || typeof node["id"] !== "string" || node["id"] === "" || typeof node["type"] !== "string") {
634
+ if (!chunkE3APHA6O_cjs.isRecord(node) || typeof node["id"] !== "string" || node["id"] === "" || typeof node["type"] !== "string") {
612
635
  throw new LiftError("Every node needs a string id and type to be lifted");
613
636
  }
614
637
  if (nodeIds.has(node["id"])) throw new LiftError(`Node id "${node["id"]}" is used twice`);
@@ -616,7 +639,7 @@ function buildPlan(normalized, options2, rawNodeIds = /* @__PURE__ */ new Set(),
616
639
  }
617
640
  const edgeIds = /* @__PURE__ */ new Set();
618
641
  for (const edge2 of edges) {
619
- if (!chunkLRM6JXJA_cjs.isRecord(edge2) || typeof edge2["source"] !== "string" || typeof edge2["target"] !== "string") {
642
+ if (!chunkE3APHA6O_cjs.isRecord(edge2) || typeof edge2["source"] !== "string" || typeof edge2["target"] !== "string") {
620
643
  throw new LiftError("Every edge needs a string source and target to be lifted");
621
644
  }
622
645
  if (edge2["id"] === void 0) continue;
@@ -624,9 +647,9 @@ function buildPlan(normalized, options2, rawNodeIds = /* @__PURE__ */ new Set(),
624
647
  if (edgeIds.has(edge2["id"])) throw new LiftError(`Edge id "${edge2["id"]}" is used twice`);
625
648
  edgeIds.add(edge2["id"]);
626
649
  }
627
- const nodeRecords = nodes2.filter(chunkLRM6JXJA_cjs.isRecord);
628
- const edgeRecords = edges.filter(chunkLRM6JXJA_cjs.isRecord);
629
- const clients = options2.registry ? chunkIZQNUNSU_cjs.clientNames(options2.registry) : /* @__PURE__ */ new Map();
650
+ const nodeRecords = nodes2.filter(chunkE3APHA6O_cjs.isRecord);
651
+ const edgeRecords = edges.filter(chunkE3APHA6O_cjs.isRecord);
652
+ const clients = options2.registry ? chunkUWQWD7BP_cjs.clientNames(options2.registry) : /* @__PURE__ */ new Map();
630
653
  const edgeIndex = /* @__PURE__ */ new Map();
631
654
  edgeRecords.forEach((edge2, index) => edgeIndex.set(edge2, index));
632
655
  const incomingByTarget = /* @__PURE__ */ new Map();
@@ -699,15 +722,21 @@ function buildPlan(normalized, options2, rawNodeIds = /* @__PURE__ */ new Set(),
699
722
  }
700
723
  function connectionsByName(connectionNames, definition) {
701
724
  const out = {};
702
- const data = chunkLRM6JXJA_cjs.isRecord(definition["data"]) ? definition["data"] : {};
725
+ const ambiguous = ambiguousConnectionNames(connectionNames);
726
+ const data = chunkE3APHA6O_cjs.isRecord(definition["data"]) ? definition["data"] : {};
703
727
  for (const node of Array.isArray(data["nodes"]) ? data["nodes"] : []) {
704
- const args = chunkLRM6JXJA_cjs.isRecord(node) && chunkLRM6JXJA_cjs.isRecord(node["args"]) ? node["args"] : void 0;
728
+ const args = chunkE3APHA6O_cjs.isRecord(node) && chunkE3APHA6O_cjs.isRecord(node["args"]) ? node["args"] : void 0;
705
729
  for (const ref of Array.isArray(args?.["connections"]) ? args["connections"] : []) {
706
- if (!chunkLRM6JXJA_cjs.isRecord(ref) || typeof ref["connectionId"] !== "string" || typeof ref["adapter"] !== "string")
730
+ if (!chunkE3APHA6O_cjs.isRecord(ref) || typeof ref["connectionId"] !== "string" || typeof ref["adapter"] !== "string")
707
731
  continue;
708
- const name = connectionNames[ref["connectionId"]];
709
- if (name !== void 0)
710
- out[name] = { connectionId: ref["connectionId"], adapter: ref["adapter"] };
732
+ const id = ref["connectionId"];
733
+ const name = Object.hasOwn(connectionNames, id) ? connectionNames[id] : void 0;
734
+ if (name === void 0 || ambiguous.has(name)) continue;
735
+ const previous = Object.hasOwn(out, name) ? out[name] : void 0;
736
+ if (previous && previous.adapter !== ref["adapter"]) {
737
+ ambiguous.add(name);
738
+ delete out[name];
739
+ } else chunkE3APHA6O_cjs.setOwn(out, name, { connectionId: id, adapter: ref["adapter"] });
711
740
  }
712
741
  }
713
742
  return out;
@@ -717,19 +746,19 @@ function connectionsByName(connectionNames, definition) {
717
746
  function descriptor(operation) {
718
747
  switch (operation.kind) {
719
748
  case "trigger": {
720
- const value2 = chunkKUTMY2IO_cjs.triggers[operation.name];
749
+ const value2 = chunkTQF7MYEN_cjs.triggers[operation.name];
721
750
  if (!value2) throw new LiftError(`Unknown trigger ${operation.name}`);
722
751
  return value2;
723
752
  }
724
753
  case "internal": {
725
- const value2 = chunkKUTMY2IO_cjs.internalNodes[operation.name];
754
+ const value2 = chunkTQF7MYEN_cjs.internalNodes[operation.name];
726
755
  if (!value2) throw new LiftError(`Unknown internal node ${operation.name}`);
727
756
  return value2;
728
757
  }
729
758
  case "client":
730
- return operation.role === "trigger" ? chunkKUTMY2IO_cjs.trigger(operation.nodeType, operation.version, operation.operation) : chunkKUTMY2IO_cjs.op(operation.nodeType, operation.version, operation.operation);
759
+ return operation.role === "trigger" ? chunkTQF7MYEN_cjs.trigger(operation.nodeType, operation.version, operation.operation) : chunkTQF7MYEN_cjs.op(operation.nodeType, operation.version, operation.operation);
731
760
  case "custom":
732
- return chunkKUTMY2IO_cjs.nodes.custom(operation.nodeType, operation.operation, operation.version);
761
+ return chunkTQF7MYEN_cjs.nodes.custom(operation.nodeType, operation.operation, operation.version);
733
762
  }
734
763
  }
735
764
  function refValue(ref, wf, runtime) {
@@ -764,7 +793,7 @@ function value(expression2, wf, runtime) {
764
793
  strings.push("");
765
794
  }
766
795
  }
767
- return chunkRRQ5HOBF_cjs.expr(Object.assign([...strings], { raw: [...strings] }), ...values);
796
+ return chunk6AIAC2FP_cjs.expr(Object.assign([...strings], { raw: [...strings] }), ...values);
768
797
  }
769
798
  case "rule": {
770
799
  const target = refValue(expression2.ref, wf, runtime);
@@ -776,7 +805,7 @@ function value(expression2, wf, runtime) {
776
805
  }
777
806
  case "group": {
778
807
  const children = expression2.children.map((child) => value(child, wf, runtime));
779
- return expression2.combinator === "and" ? chunkRRQ5HOBF_cjs.and(...children) : chunkRRQ5HOBF_cjs.or(...children);
808
+ return expression2.combinator === "and" ? chunk6AIAC2FP_cjs.and(...children) : chunk6AIAC2FP_cjs.or(...children);
780
809
  }
781
810
  case "node":
782
811
  return runtime.get(expression2.nodeId) ?? wf.ref(expression2.nodeId);
@@ -787,7 +816,7 @@ function value(expression2, wf, runtime) {
787
816
  return (declared ?? wf.ref(expression2.nodeId)).handle(expression2.handle);
788
817
  }
789
818
  case "edge":
790
- return chunkKUTMY2IO_cjs.edge(
819
+ return chunkTQF7MYEN_cjs.edge(
791
820
  value(expression2.from, wf, runtime),
792
821
  value({ k: "object", entries: expression2.options }, wf, runtime)
793
822
  );
@@ -815,7 +844,7 @@ function interpretPlan(plan) {
815
844
  k: "object",
816
845
  entries: plan.workflowOptions
817
846
  });
818
- const workflow = chunkKUTMY2IO_cjs.defineWorkflow(workflowOptions2, (wf) => {
847
+ const workflow = chunkTQF7MYEN_cjs.defineWorkflow(workflowOptions2, (wf) => {
819
848
  const runtime = /* @__PURE__ */ new Map();
820
849
  for (const statement of plan.statements) {
821
850
  if (statement.kind === "node") {
@@ -884,7 +913,7 @@ var BUILDER_METHODS = {
884
913
  };
885
914
  var atom = (text) => ({ t: "atom", text });
886
915
  function isPyIdentifier(name) {
887
- return /^[A-Za-z][A-Za-z0-9_]*$/.test(name) && !chunkIZQNUNSU_cjs.PY_KEYWORDS.has(name);
916
+ return /^[A-Za-z][A-Za-z0-9_]*$/.test(name) && !chunkUWQWD7BP_cjs.PY_KEYWORDS.has(name);
888
917
  }
889
918
  function nodeSource(nodeId, ctx) {
890
919
  const name = ctx.vars.get(nodeId);
@@ -892,7 +921,7 @@ function nodeSource(nodeId, ctx) {
892
921
  return {
893
922
  t: "call",
894
923
  func: atom("wf.ref"),
895
- args: [{ kind: "positional", value: atom(chunkIZQNUNSU_cjs.pyString(nodeId)) }]
924
+ args: [{ kind: "positional", value: atom(chunkUWQWD7BP_cjs.pyString(nodeId)) }]
896
925
  };
897
926
  }
898
927
  function refExpr(ref, ctx) {
@@ -902,21 +931,21 @@ function refExpr(ref, ctx) {
902
931
  current = { t: "subscript", base: current, indices: [atom(String(segment.index))] };
903
932
  else if (isPyIdentifier(segment.key) && !PY_REF_METHODS.has(segment.key))
904
933
  current = { t: "attr", base: current, name: segment.key };
905
- else current = { t: "subscript", base: current, indices: [atom(chunkIZQNUNSU_cjs.pyString(segment.key))] };
934
+ else current = { t: "subscript", base: current, indices: [atom(chunkUWQWD7BP_cjs.pyString(segment.key))] };
906
935
  }
907
936
  return current;
908
937
  }
909
938
  function literal(value2) {
910
939
  if (value2 === null) return atom("None");
911
940
  if (typeof value2 === "boolean") return atom(value2 ? "True" : "False");
912
- if (typeof value2 === "number") return atom(chunkIZQNUNSU_cjs.pyNumber(value2));
913
- return atom(chunkIZQNUNSU_cjs.pyString(value2));
941
+ if (typeof value2 === "number") return atom(chunkUWQWD7BP_cjs.pyNumber(value2));
942
+ return atom(chunkUWQWD7BP_cjs.pyString(value2));
914
943
  }
915
944
  function call(func, args) {
916
945
  return { t: "call", func: atom(func), args };
917
946
  }
918
947
  function keywordName(option) {
919
- return chunkIZQNUNSU_cjs.snakeCase(option);
948
+ return chunkUWQWD7BP_cjs.snakeCase(option);
920
949
  }
921
950
  function expression(planExpr, ctx) {
922
951
  switch (planExpr.k) {
@@ -926,7 +955,7 @@ function expression(planExpr, ctx) {
926
955
  return {
927
956
  t: "dict",
928
957
  entries: planExpr.entries.map(([key, child]) => [
929
- atom(chunkIZQNUNSU_cjs.pyString(key)),
958
+ atom(chunkUWQWD7BP_cjs.pyString(key)),
930
959
  expression(child, ctx)
931
960
  ])
932
961
  };
@@ -940,7 +969,7 @@ function expression(planExpr, ctx) {
940
969
  "expr",
941
970
  planExpr.parts.map((part) => ({
942
971
  kind: "positional",
943
- value: "text" in part ? atom(chunkIZQNUNSU_cjs.pyString(part.text)) : refExpr(part.ref, ctx)
972
+ value: "text" in part ? atom(chunkUWQWD7BP_cjs.pyString(part.text)) : refExpr(part.ref, ctx)
944
973
  }))
945
974
  );
946
975
  case "rule": {
@@ -954,10 +983,10 @@ function expression(planExpr, ctx) {
954
983
  right: literal(planExpr.value ?? null)
955
984
  };
956
985
  }
957
- const method = planExpr.method === "is" ? "is_" : chunkIZQNUNSU_cjs.snakeCase(planExpr.method);
986
+ const method = planExpr.method === "is" ? "is_" : chunkUWQWD7BP_cjs.snakeCase(planExpr.method);
958
987
  const args = [];
959
988
  if (planExpr.method === "is")
960
- args.push({ kind: "positional", value: atom(chunkIZQNUNSU_cjs.pyString(planExpr.operator)) });
989
+ args.push({ kind: "positional", value: atom(chunkUWQWD7BP_cjs.pyString(planExpr.operator)) });
961
990
  if (planExpr.hasValue)
962
991
  args.push({ kind: "positional", value: literal(planExpr.value ?? null) });
963
992
  return { t: "call", func: { t: "attr", base: target, name: method }, args };
@@ -976,12 +1005,12 @@ function expression(planExpr, ctx) {
976
1005
  const source = nodeSource(planExpr.nodeId, ctx);
977
1006
  const declared = ctx.declared.has(planExpr.nodeId) && ctx.vars.has(planExpr.nodeId);
978
1007
  if (declared && planExpr.accessor.kind === "property")
979
- return { t: "attr", base: source, name: chunkIZQNUNSU_cjs.snakeCase(planExpr.accessor.name) };
1008
+ return { t: "attr", base: source, name: chunkUWQWD7BP_cjs.snakeCase(planExpr.accessor.name) };
980
1009
  const method = declared && planExpr.accessor.kind === "case" ? "case" : "handle";
981
1010
  return {
982
1011
  t: "call",
983
1012
  func: { t: "attr", base: source, name: method },
984
- args: [{ kind: "positional", value: atom(chunkIZQNUNSU_cjs.pyString(planExpr.handle)) }]
1013
+ args: [{ kind: "positional", value: atom(chunkUWQWD7BP_cjs.pyString(planExpr.handle)) }]
985
1014
  };
986
1015
  }
987
1016
  case "edge":
@@ -1003,21 +1032,21 @@ function operationExpr(operation, ctx, clientPy) {
1003
1032
  switch (operation.kind) {
1004
1033
  case "trigger":
1005
1034
  ctx.used.add("triggers");
1006
- return atom(`triggers.${chunkIZQNUNSU_cjs.snakeCase(operation.name)}`);
1035
+ return atom(`triggers.${chunkUWQWD7BP_cjs.snakeCase(operation.name)}`);
1007
1036
  case "internal":
1008
1037
  ctx.used.add("nodes");
1009
- return atom(`nodes.internal.${chunkIZQNUNSU_cjs.snakeCase(operation.name)}`);
1038
+ return atom(`nodes.internal.${chunkUWQWD7BP_cjs.snakeCase(operation.name)}`);
1010
1039
  case "client":
1011
1040
  ctx.used.add("n");
1012
1041
  return atom(clientPy(operation.nodeType, operation.operation));
1013
1042
  case "custom": {
1014
1043
  ctx.used.add("nodes");
1015
- const args = [{ kind: "positional", value: atom(chunkIZQNUNSU_cjs.pyString(operation.nodeType)) }];
1044
+ const args = [{ kind: "positional", value: atom(chunkUWQWD7BP_cjs.pyString(operation.nodeType)) }];
1016
1045
  if (operation.operation !== void 0)
1017
- args.push({ kind: "positional", value: atom(chunkIZQNUNSU_cjs.pyString(operation.operation)) });
1046
+ args.push({ kind: "positional", value: atom(chunkUWQWD7BP_cjs.pyString(operation.operation)) });
1018
1047
  if (operation.version !== void 0) {
1019
1048
  args.push(
1020
- operation.operation !== void 0 ? { kind: "positional", value: atom(chunkIZQNUNSU_cjs.pyString(operation.version)) } : { kind: "keyword", name: "version", value: atom(chunkIZQNUNSU_cjs.pyString(operation.version)) }
1049
+ operation.operation !== void 0 ? { kind: "positional", value: atom(chunkUWQWD7BP_cjs.pyString(operation.version)) } : { kind: "keyword", name: "version", value: atom(chunkUWQWD7BP_cjs.pyString(operation.version)) }
1021
1050
  );
1022
1051
  }
1023
1052
  return call("nodes.custom", args);
@@ -1026,7 +1055,7 @@ function operationExpr(operation, ctx, clientPy) {
1026
1055
  }
1027
1056
  function statementLines(statement, ctx, clientPy) {
1028
1057
  if (statement.kind === "edgeOrder") {
1029
- return chunkIZQNUNSU_cjs.formatLines(
1058
+ return chunkUWQWD7BP_cjs.formatLines(
1030
1059
  "",
1031
1060
  call("wf.edge_order_is", [
1032
1061
  { kind: "positional", value: { t: "list", items: statement.ids.map((id) => literal(id)) } }
@@ -1038,28 +1067,28 @@ function statementLines(statement, ctx, clientPy) {
1038
1067
  if (statement.kind === "connect") {
1039
1068
  const args2 = [
1040
1069
  { kind: "positional", value: expression(statement.from, ctx) },
1041
- { kind: "positional", value: atom(chunkIZQNUNSU_cjs.pyString(statement.to)) },
1070
+ { kind: "positional", value: atom(chunkUWQWD7BP_cjs.pyString(statement.to)) },
1042
1071
  ...keywords(statement.options, ctx)
1043
1072
  ];
1044
- return chunkIZQNUNSU_cjs.formatLines("", call("wf.connect", args2), "", 1);
1073
+ return chunkUWQWD7BP_cjs.formatLines("", call("wf.connect", args2), "", 1);
1045
1074
  }
1046
1075
  const args = [
1047
1076
  ...statement.operation ? [{ kind: "positional", value: operationExpr(statement.operation, ctx, clientPy) }] : [],
1048
1077
  ...keywords(statement.options, ctx)
1049
1078
  ];
1050
- const method = BUILDER_METHODS[statement.method] ?? chunkIZQNUNSU_cjs.snakeCase(statement.method);
1079
+ const method = BUILDER_METHODS[statement.method] ?? chunkUWQWD7BP_cjs.snakeCase(statement.method);
1051
1080
  const callExpr = call(`wf.${method}`, args);
1052
1081
  ctx.declared.add(statement.nodeId);
1053
1082
  const name = ctx.vars.get(statement.nodeId);
1054
- return chunkIZQNUNSU_cjs.formatLines(name !== void 0 ? `${name} = ` : "", callExpr, "", 1);
1083
+ return chunkUWQWD7BP_cjs.formatLines(name !== void 0 ? `${name} = ` : "", callExpr, "", 1);
1055
1084
  }
1056
1085
  function renderPython(plan, clientPy, header = []) {
1057
- const allocator = new chunkIZQNUNSU_cjs.NameAllocator("py");
1086
+ const allocator = new chunkUWQWD7BP_cjs.NameAllocator("py");
1058
1087
  const vars = /* @__PURE__ */ new Map();
1059
- for (const nodeId of chunkIZQNUNSU_cjs.referencedLater(plan)) vars.set(nodeId, allocator.forNode(nodeId));
1088
+ for (const nodeId of chunkUWQWD7BP_cjs.referencedLater(plan)) vars.set(nodeId, allocator.forNode(nodeId));
1060
1089
  const ctx = { vars, declared: /* @__PURE__ */ new Set(), used: /* @__PURE__ */ new Set() };
1061
1090
  const body = plan.statements.flatMap((statement) => statementLines(statement, ctx, clientPy));
1062
- const decorator = chunkIZQNUNSU_cjs.formatLines(
1091
+ const decorator = chunkUWQWD7BP_cjs.formatLines(
1063
1092
  "@",
1064
1093
  call("define_workflow", keywords(plan.workflowOptions, ctx)),
1065
1094
  "",
@@ -1071,12 +1100,12 @@ function renderPython(plan, clientPy, header = []) {
1071
1100
  const lines = [
1072
1101
  ...header.map((line) => `# ${line}`),
1073
1102
  ...header.length > 0 ? [""] : [],
1074
- ...chunkIZQNUNSU_cjs.formatImport(PY_SDK_MODULE, sdkNames),
1075
- ...ctx.used.has("n") ? chunkIZQNUNSU_cjs.formatImport(PY_PROJECT_MODULE, ["nodes as n"]) : [],
1103
+ ...chunkUWQWD7BP_cjs.formatImport(PY_SDK_MODULE, sdkNames),
1104
+ ...ctx.used.has("n") ? chunkUWQWD7BP_cjs.formatImport(PY_PROJECT_MODULE, ["nodes as n"]) : [],
1076
1105
  "",
1077
1106
  "",
1078
1107
  ...decorator,
1079
- `def ${chunkIZQNUNSU_cjs.pyWorkflowName(plan.key)}(wf):`,
1108
+ `def ${chunkUWQWD7BP_cjs.pyWorkflowName(plan.key)}(wf):`,
1080
1109
  ...body.length > 0 ? body : [" pass"],
1081
1110
  ""
1082
1111
  ];
@@ -1085,53 +1114,84 @@ function renderPython(plan, clientPy, header = []) {
1085
1114
 
1086
1115
  // src/roundtrip/lift.ts
1087
1116
  function layoutOf(reference) {
1088
- const data = chunkLRM6JXJA_cjs.isRecord(reference["data"]) ? reference["data"] : {};
1117
+ const data = chunkE3APHA6O_cjs.isRecord(reference["data"]) ? reference["data"] : {};
1089
1118
  const positions = {};
1090
1119
  for (const node of Array.isArray(data["nodes"]) ? data["nodes"] : []) {
1091
- if (!chunkLRM6JXJA_cjs.isRecord(node) || typeof node["id"] !== "string" || !chunkLRM6JXJA_cjs.isRecord(node["position"])) continue;
1120
+ if (!chunkE3APHA6O_cjs.isRecord(node) || typeof node["id"] !== "string" || !chunkE3APHA6O_cjs.isRecord(node["position"])) continue;
1092
1121
  const { x, y } = node["position"];
1093
- if (typeof x === "number" && typeof y === "number") positions[node["id"]] = { x, y };
1122
+ if (typeof x === "number" && typeof y === "number") chunkE3APHA6O_cjs.setOwn(positions, node["id"], { x, y });
1094
1123
  }
1095
1124
  const sidecar = {
1096
- format: chunkKUTMY2IO_cjs.LAYOUT_FORMAT,
1097
- formatVersion: chunkKUTMY2IO_cjs.LAYOUT_FORMAT_VERSION,
1125
+ format: chunkTQF7MYEN_cjs.LAYOUT_FORMAT,
1126
+ formatVersion: chunkTQF7MYEN_cjs.LAYOUT_FORMAT_VERSION,
1098
1127
  positions
1099
1128
  };
1100
1129
  if (Array.isArray(data["stickyNotes"])) sidecar.stickyNotes = data["stickyNotes"];
1101
- const meta = chunkLRM6JXJA_cjs.isRecord(reference["meta"]) ? reference["meta"] : void 0;
1102
- if (chunkLRM6JXJA_cjs.isRecord(meta?.["layout"])) sidecar.metaLayout = meta["layout"];
1130
+ const meta = chunkE3APHA6O_cjs.isRecord(reference["meta"]) ? reference["meta"] : void 0;
1131
+ if (chunkE3APHA6O_cjs.isRecord(meta?.["layout"])) sidecar.metaLayout = meta["layout"];
1103
1132
  return sidecar;
1104
1133
  }
1105
1134
  function mismatches(reference, candidate) {
1106
- const refData = chunkLRM6JXJA_cjs.isRecord(reference["data"]) ? reference["data"] : {};
1107
- const candData = chunkLRM6JXJA_cjs.isRecord(candidate["data"]) ? candidate["data"] : {};
1135
+ const refData = chunkE3APHA6O_cjs.isRecord(reference["data"]) ? reference["data"] : {};
1136
+ const candData = chunkE3APHA6O_cjs.isRecord(candidate["data"]) ? candidate["data"] : {};
1108
1137
  const byId = (items) => new Map(
1109
- (Array.isArray(items) ? items : []).filter(chunkLRM6JXJA_cjs.isRecord).map((item) => [String(item["id"]), item])
1138
+ (Array.isArray(items) ? items : []).filter(chunkE3APHA6O_cjs.isRecord).map((item) => [String(item["id"]), item])
1110
1139
  );
1111
1140
  const nodes2 = /* @__PURE__ */ new Set();
1112
1141
  const candNodes = byId(candData["nodes"]);
1113
1142
  for (const [id, node] of byId(refData["nodes"]))
1114
- if (!chunkLRM6JXJA_cjs.deepEqual(node, candNodes.get(id))) nodes2.add(id);
1143
+ if (!chunkE3APHA6O_cjs.deepEqual(node, candNodes.get(id))) nodes2.add(id);
1115
1144
  const edges = /* @__PURE__ */ new Set();
1116
1145
  const refEdges = Array.isArray(refData["edges"]) ? refData["edges"] : [];
1117
1146
  const candEdges = Array.isArray(candData["edges"]) ? candData["edges"] : [];
1118
1147
  refEdges.forEach((edge2, index) => {
1119
- if (!chunkLRM6JXJA_cjs.deepEqual(edge2, candEdges[index])) edges.add(index);
1148
+ if (!chunkE3APHA6O_cjs.deepEqual(edge2, candEdges[index])) edges.add(index);
1120
1149
  });
1121
1150
  const strip = (doc) => {
1122
1151
  const copy = { ...doc };
1123
1152
  delete copy["authoring"];
1124
- const data = chunkLRM6JXJA_cjs.isRecord(copy["data"]) ? { ...copy["data"] } : {};
1153
+ const data = chunkE3APHA6O_cjs.isRecord(copy["data"]) ? { ...copy["data"] } : {};
1125
1154
  delete data["nodes"];
1126
1155
  delete data["edges"];
1127
1156
  copy["data"] = data;
1128
1157
  return copy;
1129
1158
  };
1130
- return { nodes: nodes2, edges, document: !chunkLRM6JXJA_cjs.deepEqual(strip(reference), strip(candidate)) };
1159
+ return { nodes: nodes2, edges, document: !chunkE3APHA6O_cjs.deepEqual(strip(reference), strip(candidate)) };
1160
+ }
1161
+ function tryRun(attempt) {
1162
+ try {
1163
+ return attempt();
1164
+ } catch (error) {
1165
+ if (error instanceof chunk6AIAC2FP_cjs.BuilderError) return void 0;
1166
+ throw error;
1167
+ }
1168
+ }
1169
+ function rejectedByBuilder(reference, run) {
1170
+ const nodes2 = /* @__PURE__ */ new Set();
1171
+ const edges = /* @__PURE__ */ new Set();
1172
+ const data = chunkE3APHA6O_cjs.isRecord(reference["data"]) ? reference["data"] : {};
1173
+ const nodeIds = (Array.isArray(data["nodes"]) ? data["nodes"] : []).flatMap(
1174
+ (node) => chunkE3APHA6O_cjs.isRecord(node) && typeof node["id"] === "string" ? [node["id"]] : []
1175
+ );
1176
+ const edgeCount = Array.isArray(data["edges"]) ? data["edges"].length : 0;
1177
+ const edgeIndices = Array.from({ length: edgeCount }, (_, index) => index);
1178
+ const allNodes = new Set(nodeIds);
1179
+ const allEdges = new Set(edgeIndices);
1180
+ for (const id of nodeIds) {
1181
+ const others = new Set(allNodes);
1182
+ others.delete(id);
1183
+ if (tryRun(() => run(others, allEdges)) === void 0) nodes2.add(id);
1184
+ }
1185
+ for (const index of edgeIndices) {
1186
+ const others = new Set(allEdges);
1187
+ others.delete(index);
1188
+ if (tryRun(() => run(allNodes, others)) === void 0) edges.add(index);
1189
+ }
1190
+ return { nodes: nodes2, edges };
1131
1191
  }
1132
1192
  function prepareLift(definition, options2 = {}) {
1133
- const normalized = chunkAU3YW7FZ_cjs.normalizeDefinition(definition);
1134
- if (!chunkLRM6JXJA_cjs.isRecord(normalized) || !chunkLRM6JXJA_cjs.isRecord(normalized["data"]))
1193
+ const normalized = chunk7YR7DI7B_cjs.normalizeDefinition(definition);
1194
+ if (!chunkE3APHA6O_cjs.isRecord(normalized) || !chunkE3APHA6O_cjs.isRecord(normalized["data"]))
1135
1195
  throw new TypeError("A workflow definition must be an object with data");
1136
1196
  const reference = { ...normalized };
1137
1197
  const items = [];
@@ -1151,7 +1211,7 @@ function prepareLift(definition, options2 = {}) {
1151
1211
  kind: "layout-omitted",
1152
1212
  detail: "Node positions, sticky notes and meta.layout are not exported"
1153
1213
  });
1154
- const pinned = chunkLRM6JXJA_cjs.isRecord(reference["pinnedData"]) ? (
1214
+ const pinned = chunkE3APHA6O_cjs.isRecord(reference["pinnedData"]) ? (
1155
1215
  // Checked to be a record; carried verbatim.
1156
1216
  reference["pinnedData"]
1157
1217
  ) : void 0;
@@ -1161,16 +1221,25 @@ function prepareLift(definition, options2 = {}) {
1161
1221
  const run = (rawNodes, rawEdges) => {
1162
1222
  const build = buildPlan(reference, options2, rawNodes, rawEdges);
1163
1223
  const recording = interpretPlan(build.plan);
1164
- const candidate = chunkKUTMY2IO_cjs.assembleRecording(recording, {
1224
+ const candidate = chunkTQF7MYEN_cjs.assembleRecording(recording, {
1165
1225
  layout,
1166
1226
  ...connections ? { connections } : {},
1167
1227
  ...pinned ? { pinnedData: pinned } : {}
1168
1228
  });
1169
- return { build, candidate: chunkAU3YW7FZ_cjs.normalizeDefinition(candidate) };
1229
+ return { build, candidate: chunk7YR7DI7B_cjs.normalizeDefinition(candidate) };
1170
1230
  };
1171
- let attempt = run(/* @__PURE__ */ new Set(), /* @__PURE__ */ new Set());
1231
+ let rejected = { nodes: /* @__PURE__ */ new Set(), edges: /* @__PURE__ */ new Set() };
1232
+ let attempt = tryRun(() => run(rejected.nodes, rejected.edges));
1233
+ if (attempt === void 0) {
1234
+ rejected = rejectedByBuilder(reference, run);
1235
+ attempt = run(rejected.nodes, rejected.edges);
1236
+ }
1172
1237
  const first = mismatches(reference, attempt.candidate);
1173
- if (first.nodes.size > 0 || first.edges.size > 0) attempt = run(first.nodes, first.edges);
1238
+ if (first.nodes.size > 0 || first.edges.size > 0)
1239
+ attempt = run(
1240
+ /* @__PURE__ */ new Set([...rejected.nodes, ...first.nodes]),
1241
+ /* @__PURE__ */ new Set([...rejected.edges, ...first.edges])
1242
+ );
1174
1243
  const residual = mismatches(reference, attempt.candidate);
1175
1244
  for (const id of residual.nodes)
1176
1245
  items.push({
@@ -1228,27 +1297,27 @@ function sidecarFiles(prepared) {
1228
1297
  files.push({
1229
1298
  path: `workflows/${key}.layout.json`,
1230
1299
  contentType: "application/json",
1231
- content: chunk27HASETB_cjs.stableStringify(prepared.layout)
1300
+ content: chunkCSYBNN3V_cjs.stableStringify(prepared.layout)
1232
1301
  });
1233
1302
  }
1234
1303
  if (prepared.pinnedData) {
1235
1304
  files.push({
1236
1305
  path: `workflows/${key}.pinned.json`,
1237
1306
  contentType: "application/json",
1238
- content: chunk27HASETB_cjs.stableStringify(prepared.pinnedData)
1307
+ content: chunkCSYBNN3V_cjs.stableStringify(prepared.pinnedData)
1239
1308
  });
1240
1309
  }
1241
1310
  return files;
1242
1311
  }
1243
1312
  async function liftToTypeScript(definition, options2 = {}) {
1244
1313
  const prepared = prepareLift(definition, options2);
1245
- const source = await chunkIZQNUNSU_cjs.renderTypeScript(prepared.plan, headerLines(options2.header));
1314
+ const source = await chunkUWQWD7BP_cjs.renderTypeScript(prepared.plan, headerLines(options2.header));
1246
1315
  const files = [
1247
1316
  { path: `workflows/${prepared.plan.key}.ts`, contentType: "text/typescript", content: source },
1248
1317
  ...sidecarFiles(prepared)
1249
1318
  ];
1250
1319
  if (prepared.usesClients) {
1251
- const clients = await chunkIZQNUNSU_cjs.generateNodeClients(prepared.registry, "ts");
1320
+ const clients = await chunkUWQWD7BP_cjs.generateNodeClients(prepared.registry, "ts");
1252
1321
  files.push({ path: clients.path, contentType: "text/typescript", content: clients.content });
1253
1322
  }
1254
1323
  return { files, items: prepared.items, reference: prepared.reference };
@@ -1258,14 +1327,14 @@ async function liftToPython(definition, options2 = {}) {
1258
1327
  const source = renderPython(prepared.plan, prepared.clientPy, headerLines(options2.header));
1259
1328
  const files = [
1260
1329
  {
1261
- path: `workflows/${chunkIZQNUNSU_cjs.pyWorkflowName(prepared.plan.key)}.py`,
1330
+ path: `workflows/${chunkUWQWD7BP_cjs.pyWorkflowName(prepared.plan.key)}.py`,
1262
1331
  contentType: "text/x-python",
1263
1332
  content: source
1264
1333
  },
1265
1334
  ...sidecarFiles(prepared)
1266
1335
  ];
1267
1336
  if (prepared.usesClients) {
1268
- const clients = await chunkIZQNUNSU_cjs.generateNodeClients(prepared.registry, "py");
1337
+ const clients = await chunkUWQWD7BP_cjs.generateNodeClients(prepared.registry, "py");
1269
1338
  files.push({ path: clients.path, contentType: "text/x-python", content: clients.content });
1270
1339
  }
1271
1340
  return { files, items: prepared.items, reference: prepared.reference };
@@ -1280,9 +1349,9 @@ var LOSSY_KINDS = /* @__PURE__ */ new Set([
1280
1349
  ]);
1281
1350
  async function checkFidelity(files, reference, items, options2 = {}) {
1282
1351
  const all = [...items];
1283
- const connections = options2.connectionNames && chunkLRM6JXJA_cjs.isRecord(reference) ? connectionsByName(options2.connectionNames, reference) : void 0;
1352
+ const connections = options2.connectionNames && chunkE3APHA6O_cjs.isRecord(reference) ? connectionsByName(options2.connectionNames, reference) : void 0;
1284
1353
  try {
1285
- const result = await chunkLUXCXFOE_cjs.lower(
1354
+ const result = await chunkY7NWR3WH_cjs.lower(
1286
1355
  files.map((file) => ({ path: file.path, content: file.content })),
1287
1356
  {
1288
1357
  ...options2.esbuild ? { esbuild: options2.esbuild } : {},
@@ -1296,8 +1365,8 @@ async function checkFidelity(files, reference, items, options2 = {}) {
1296
1365
  kind: "lowering-failed",
1297
1366
  detail: `Lowering produced ${result.workflows.length} workflows instead of one`
1298
1367
  });
1299
- } else if (chunkAU3YW7FZ_cjs.irHash(lowered) !== chunkAU3YW7FZ_cjs.irHash(reference)) {
1300
- for (const change of chunkBYJ7QTLY_cjs.diffDefinitions(reference, lowered)) {
1368
+ } else if (chunk7YR7DI7B_cjs.irHash(lowered) !== chunk7YR7DI7B_cjs.irHash(reference)) {
1369
+ for (const change of chunkTWOYB4Y7_cjs.diffDefinitions(reference, lowered)) {
1301
1370
  all.push({
1302
1371
  path: change.path,
1303
1372
  kind: "roundtrip-mismatch",
@@ -1322,48 +1391,52 @@ async function exportWorkflowCode(definition, options2) {
1322
1391
  ...options2.connectionNames ? { connectionNames: options2.connectionNames } : {}
1323
1392
  });
1324
1393
  const files = options2.format === "PYTHON" ? (await liftToPython(definition, options2)).files : ts.files;
1325
- return { format: options2.format, files, fidelity, irHash: chunkAU3YW7FZ_cjs.irHash(definition) };
1394
+ return { format: options2.format, files, fidelity, irHash: chunk7YR7DI7B_cjs.irHash(definition) };
1326
1395
  }
1327
1396
 
1328
1397
  Object.defineProperty(exports, "PY_LINE_LENGTH", {
1329
1398
  enumerable: true,
1330
- get: function () { return chunkIZQNUNSU_cjs.PY_LINE_LENGTH; }
1399
+ get: function () { return chunkUWQWD7BP_cjs.PY_LINE_LENGTH; }
1331
1400
  });
1332
1401
  Object.defineProperty(exports, "TS_FORMAT_OPTIONS", {
1333
1402
  enumerable: true,
1334
- get: function () { return chunkIZQNUNSU_cjs.TS_FORMAT_OPTIONS; }
1403
+ get: function () { return chunkUWQWD7BP_cjs.TS_FORMAT_OPTIONS; }
1335
1404
  });
1336
1405
  Object.defineProperty(exports, "TS_NODES_IMPORT", {
1337
1406
  enumerable: true,
1338
- get: function () { return chunkIZQNUNSU_cjs.TS_NODES_IMPORT; }
1407
+ get: function () { return chunkUWQWD7BP_cjs.TS_NODES_IMPORT; }
1339
1408
  });
1340
1409
  Object.defineProperty(exports, "createNodeVmEvaluator", {
1341
1410
  enumerable: true,
1342
- get: function () { return chunk265J2FCH_cjs.createNodeVmEvaluator; }
1411
+ get: function () { return chunk3M34AUIY_cjs.createNodeVmEvaluator; }
1412
+ });
1413
+ Object.defineProperty(exports, "DeterminismViolationError", {
1414
+ enumerable: true,
1415
+ get: function () { return chunkY7NWR3WH_cjs.DeterminismViolationError; }
1343
1416
  });
1344
1417
  Object.defineProperty(exports, "ESBUILD_VERSION", {
1345
1418
  enumerable: true,
1346
- get: function () { return chunkLUXCXFOE_cjs.ESBUILD_VERSION; }
1419
+ get: function () { return chunkY7NWR3WH_cjs.ESBUILD_VERSION; }
1347
1420
  });
1348
1421
  Object.defineProperty(exports, "EVALUATION_GLOBAL", {
1349
1422
  enumerable: true,
1350
- get: function () { return chunkLUXCXFOE_cjs.EVALUATION_GLOBAL; }
1423
+ get: function () { return chunkY7NWR3WH_cjs.EVALUATION_GLOBAL; }
1351
1424
  });
1352
1425
  Object.defineProperty(exports, "LowerError", {
1353
1426
  enumerable: true,
1354
- get: function () { return chunkLUXCXFOE_cjs.LowerError; }
1427
+ get: function () { return chunkY7NWR3WH_cjs.LowerError; }
1355
1428
  });
1356
1429
  Object.defineProperty(exports, "bundleProject", {
1357
1430
  enumerable: true,
1358
- get: function () { return chunkLUXCXFOE_cjs.bundleProject; }
1431
+ get: function () { return chunkY7NWR3WH_cjs.bundleProject; }
1359
1432
  });
1360
1433
  Object.defineProperty(exports, "defaultEntries", {
1361
1434
  enumerable: true,
1362
- get: function () { return chunkLUXCXFOE_cjs.defaultEntries; }
1435
+ get: function () { return chunkY7NWR3WH_cjs.defaultEntries; }
1363
1436
  });
1364
1437
  Object.defineProperty(exports, "lower", {
1365
1438
  enumerable: true,
1366
- get: function () { return chunkLUXCXFOE_cjs.lower; }
1439
+ get: function () { return chunkY7NWR3WH_cjs.lower; }
1367
1440
  });
1368
1441
  exports.LiftError = LiftError;
1369
1442
  exports.PY_PROJECT_MODULE = PY_PROJECT_MODULE;