@synergenius/flow-weaver 0.10.1 → 0.10.2

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.
package/README.md CHANGED
@@ -1,8 +1,12 @@
1
1
  # @synergenius/flow-weaver
2
2
 
3
- [![npm version](https://img.shields.io/npm/v/@synergenius/flow-weaver.svg)](https://www.npmjs.com/package/@synergenius/flow-weaver)
4
- [![License: Flow Weaver Library License](https://img.shields.io/badge/License-Flow%20Weaver%20Library-blue.svg)](./LICENSE)
5
- [![Node.js](https://img.shields.io/badge/Node.js-%3E%3D18-green.svg)](https://nodejs.org)
3
+ [![npm version](https://img.shields.io/npm/v/@synergenius/flow-weaver?style=flat)](https://www.npmjs.com/package/@synergenius/flow-weaver)
4
+ [![npm downloads](https://img.shields.io/npm/dw/@synergenius/flow-weaver?style=flat)](https://www.npmjs.com/package/@synergenius/flow-weaver)
5
+ [![CI](https://img.shields.io/github/actions/workflow/status/synergenius-fw/flow-weaver/ci.yml?branch=main&style=flat)](https://github.com/synergenius-fw/flow-weaver/actions/workflows/ci.yml)
6
+ [![Tests](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/moraispgsi/305430ef59a51d0a58eb61fefdfbe634/raw/flow-weaver-test-count.json&style=flat)](https://github.com/synergenius-fw/flow-weaver/actions/workflows/ci.yml)
7
+ [![Coverage](https://img.shields.io/codecov/c/github/synergenius-fw/flow-weaver?style=flat)](https://codecov.io/gh/synergenius-fw/flow-weaver)
8
+ [![License: Flow Weaver Library License](https://img.shields.io/badge/License-Flow%20Weaver%20Library-blue?style=flat)](./LICENSE)
9
+ [![Node.js](https://img.shields.io/badge/Node.js-%3E%3D18-green?style=flat)](https://nodejs.org)
6
10
 
7
11
  **Build AI agent workflows visually. Ship them as your own code.**
8
12
 
@@ -16881,6 +16881,121 @@ var require_browser = __commonJS({
16881
16881
  }
16882
16882
  });
16883
16883
 
16884
+ // node_modules/has-flag/index.js
16885
+ var require_has_flag = __commonJS({
16886
+ "node_modules/has-flag/index.js"(exports2, module2) {
16887
+ "use strict";
16888
+ module2.exports = (flag, argv = process.argv) => {
16889
+ const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
16890
+ const position = argv.indexOf(prefix + flag);
16891
+ const terminatorPosition = argv.indexOf("--");
16892
+ return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
16893
+ };
16894
+ }
16895
+ });
16896
+
16897
+ // node_modules/supports-color/index.js
16898
+ var require_supports_color = __commonJS({
16899
+ "node_modules/supports-color/index.js"(exports2, module2) {
16900
+ "use strict";
16901
+ var os3 = __require("os");
16902
+ var tty = __require("tty");
16903
+ var hasFlag = require_has_flag();
16904
+ var { env } = process;
16905
+ var forceColor;
16906
+ if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) {
16907
+ forceColor = 0;
16908
+ } else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) {
16909
+ forceColor = 1;
16910
+ }
16911
+ if ("FORCE_COLOR" in env) {
16912
+ if (env.FORCE_COLOR === "true") {
16913
+ forceColor = 1;
16914
+ } else if (env.FORCE_COLOR === "false") {
16915
+ forceColor = 0;
16916
+ } else {
16917
+ forceColor = env.FORCE_COLOR.length === 0 ? 1 : Math.min(parseInt(env.FORCE_COLOR, 10), 3);
16918
+ }
16919
+ }
16920
+ function translateLevel(level) {
16921
+ if (level === 0) {
16922
+ return false;
16923
+ }
16924
+ return {
16925
+ level,
16926
+ hasBasic: true,
16927
+ has256: level >= 2,
16928
+ has16m: level >= 3
16929
+ };
16930
+ }
16931
+ function supportsColor(haveStream, streamIsTTY) {
16932
+ if (forceColor === 0) {
16933
+ return 0;
16934
+ }
16935
+ if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) {
16936
+ return 3;
16937
+ }
16938
+ if (hasFlag("color=256")) {
16939
+ return 2;
16940
+ }
16941
+ if (haveStream && !streamIsTTY && forceColor === void 0) {
16942
+ return 0;
16943
+ }
16944
+ const min = forceColor || 0;
16945
+ if (env.TERM === "dumb") {
16946
+ return min;
16947
+ }
16948
+ if (process.platform === "win32") {
16949
+ const osRelease = os3.release().split(".");
16950
+ if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
16951
+ return Number(osRelease[2]) >= 14931 ? 3 : 2;
16952
+ }
16953
+ return 1;
16954
+ }
16955
+ if ("CI" in env) {
16956
+ if (["TRAVIS", "CIRCLECI", "APPVEYOR", "GITLAB_CI", "GITHUB_ACTIONS", "BUILDKITE"].some((sign) => sign in env) || env.CI_NAME === "codeship") {
16957
+ return 1;
16958
+ }
16959
+ return min;
16960
+ }
16961
+ if ("TEAMCITY_VERSION" in env) {
16962
+ return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
16963
+ }
16964
+ if (env.COLORTERM === "truecolor") {
16965
+ return 3;
16966
+ }
16967
+ if ("TERM_PROGRAM" in env) {
16968
+ const version3 = parseInt((env.TERM_PROGRAM_VERSION || "").split(".")[0], 10);
16969
+ switch (env.TERM_PROGRAM) {
16970
+ case "iTerm.app":
16971
+ return version3 >= 3 ? 3 : 2;
16972
+ case "Apple_Terminal":
16973
+ return 2;
16974
+ }
16975
+ }
16976
+ if (/-256(color)?$/i.test(env.TERM)) {
16977
+ return 2;
16978
+ }
16979
+ if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
16980
+ return 1;
16981
+ }
16982
+ if ("COLORTERM" in env) {
16983
+ return 1;
16984
+ }
16985
+ return min;
16986
+ }
16987
+ function getSupportLevel(stream2) {
16988
+ const level = supportsColor(stream2, stream2 && stream2.isTTY);
16989
+ return translateLevel(level);
16990
+ }
16991
+ module2.exports = {
16992
+ supportsColor: getSupportLevel,
16993
+ stdout: translateLevel(supportsColor(true, tty.isatty(1))),
16994
+ stderr: translateLevel(supportsColor(true, tty.isatty(2)))
16995
+ };
16996
+ }
16997
+ });
16998
+
16884
16999
  // node_modules/debug/src/node.js
16885
17000
  var require_node = __commonJS({
16886
17001
  "node_modules/debug/src/node.js"(exports2, module2) {
@@ -16899,7 +17014,7 @@ var require_node = __commonJS({
16899
17014
  );
16900
17015
  exports2.colors = [6, 2, 3, 4, 5, 1];
16901
17016
  try {
16902
- const supportsColor = __require("supports-color");
17017
+ const supportsColor = require_supports_color();
16903
17018
  if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) {
16904
17019
  exports2.colors = [
16905
17020
  20,
@@ -61065,12 +61180,12 @@ function renderConnection(parts2, conn, gradIndex) {
61065
61180
  ` <path d="${conn.path}" fill="none" stroke="url(#conn-grad-${gradIndex})" stroke-width="3"${dashAttr} stroke-linecap="round" data-source="${escapeXml(conn.fromNode)}.${escapeXml(conn.fromPort)}:output" data-target="${escapeXml(conn.toNode)}.${escapeXml(conn.toPort)}:input"/>`
61066
61181
  );
61067
61182
  }
61068
- function renderScopeConnection(parts2, conn, allConnections) {
61183
+ function renderScopeConnection(parts2, conn, allConnections, parentNodeId) {
61069
61184
  const gradIndex = allConnections.indexOf(conn);
61070
61185
  if (gradIndex < 0) return;
61071
61186
  const dashAttr = conn.isStepConnection ? "" : ' stroke-dasharray="8 4"';
61072
61187
  parts2.push(
61073
- ` <path d="${conn.path}" fill="none" stroke="url(#conn-grad-${gradIndex})" stroke-width="2.5"${dashAttr} stroke-linecap="round" data-source="${escapeXml(conn.fromNode)}.${escapeXml(conn.fromPort)}:output" data-target="${escapeXml(conn.toNode)}.${escapeXml(conn.toPort)}:input"/>`
61188
+ ` <path d="${conn.path}" fill="none" stroke="url(#conn-grad-${gradIndex})" stroke-width="2.5"${dashAttr} stroke-linecap="round" data-source="${escapeXml(conn.fromNode)}.${escapeXml(conn.fromPort)}:output" data-target="${escapeXml(conn.toNode)}.${escapeXml(conn.toPort)}:input" data-scope="${escapeXml(parentNodeId)}"/>`
61074
61189
  );
61075
61190
  }
61076
61191
  function renderNodeBody(parts2, node, theme, indent) {
@@ -61114,7 +61229,7 @@ function renderScopedContent(parts2, node, theme, themeName, allConnections) {
61114
61229
  ` <rect x="${scopeX}" y="${scopeY}" width="${scopeW}" height="${scopeH}" rx="4" fill="none" stroke="${theme.scopeAreaStroke}" stroke-width="1" stroke-dasharray="4 2" opacity="0.5"/>`
61115
61230
  );
61116
61231
  for (const conn of node.scopeConnections ?? []) {
61117
- renderScopeConnection(parts2, conn, allConnections);
61232
+ renderScopeConnection(parts2, conn, allConnections, node.id);
61118
61233
  }
61119
61234
  if (scopePorts) {
61120
61235
  renderPortDots(parts2, node.id, scopePorts.inputs, scopePorts.outputs, themeName);
@@ -61662,7 +61777,7 @@ path[data-source].port-hover { opacity: 1; }
61662
61777
  var connIndex = [];
61663
61778
  content.querySelectorAll('path[data-source]').forEach(function(p) {
61664
61779
  var src = p.getAttribute('data-source'), tgt = p.getAttribute('data-target');
61665
- connIndex.push({ el: p, src: src, tgt: tgt, srcNode: src.split('.')[0], tgtNode: tgt.split('.')[0] });
61780
+ connIndex.push({ el: p, src: src, tgt: tgt, srcNode: src.split('.')[0], tgtNode: tgt.split('.')[0], scopeOf: p.getAttribute('data-scope') || null });
61666
61781
  });
61667
61782
 
61668
61783
  // Snapshot of original port positions for reset
@@ -61704,9 +61819,18 @@ path[data-source].port-hover { opacity: 1; }
61704
61819
  off.dx += dx; off.dy += dy;
61705
61820
  var tr = 'translate(' + off.dx + ',' + off.dy + ')';
61706
61821
 
61707
- // Move node group
61822
+ // Move node group (if nested inside a scoped parent, subtract parent offset)
61708
61823
  var nodeG = content.querySelector('.nodes [data-node-id="' + CSS.escape(nodeId) + '"]');
61709
- if (nodeG) nodeG.setAttribute('transform', tr);
61824
+ if (nodeG) {
61825
+ var parentNodeG = nodeG.parentElement ? nodeG.parentElement.closest('[data-node-id]') : null;
61826
+ if (parentNodeG) {
61827
+ var parentId = parentNodeG.getAttribute('data-node-id');
61828
+ var parentOff = nodeOffsets[parentId] || { dx: 0, dy: 0 };
61829
+ nodeG.setAttribute('transform', 'translate(' + (off.dx - parentOff.dx) + ',' + (off.dy - parentOff.dy) + ')');
61830
+ } else {
61831
+ nodeG.setAttribute('transform', tr);
61832
+ }
61833
+ }
61710
61834
 
61711
61835
  // Move label
61712
61836
  var labelG = content.querySelector('[data-label-for="' + CSS.escape(nodeId) + '"]');
@@ -61753,11 +61877,20 @@ path[data-source].port-hover { opacity: 1; }
61753
61877
  });
61754
61878
  }
61755
61879
 
61756
- // Recalculate affected connection paths
61880
+ // Recalculate affected connection paths (skip scope connections when parent is dragged \u2014 they move with the group transform)
61757
61881
  connIndex.forEach(function(c) {
61882
+ if (c.scopeOf === nodeId) return;
61758
61883
  if (c.srcNode === nodeId || c.tgtNode === nodeId) {
61759
61884
  var sp = portPositions[c.src], tp = portPositions[c.tgt];
61760
- if (sp && tp) c.el.setAttribute('d', computeConnectionPath(sp.cx, sp.cy, tp.cx, tp.cy));
61885
+ if (sp && tp) {
61886
+ if (c.scopeOf) {
61887
+ // Scope connection paths live inside the parent group; use parent-local coords
61888
+ var pOff = nodeOffsets[c.scopeOf] || { dx: 0, dy: 0 };
61889
+ c.el.setAttribute('d', computeConnectionPath(sp.cx - pOff.dx, sp.cy - pOff.dy, tp.cx - pOff.dx, tp.cy - pOff.dy));
61890
+ } else {
61891
+ c.el.setAttribute('d', computeConnectionPath(sp.cx, sp.cy, tp.cx, tp.cy));
61892
+ }
61893
+ }
61761
61894
  }
61762
61895
  if (nodeG) {
61763
61896
  var children = nodeG.querySelectorAll(':scope > g[data-node-id]');
@@ -61765,7 +61898,14 @@ path[data-source].port-hover { opacity: 1; }
61765
61898
  var childId = childG.getAttribute('data-node-id');
61766
61899
  if (c.srcNode === childId || c.tgtNode === childId) {
61767
61900
  var sp = portPositions[c.src], tp = portPositions[c.tgt];
61768
- if (sp && tp) c.el.setAttribute('d', computeConnectionPath(sp.cx, sp.cy, tp.cx, tp.cy));
61901
+ if (sp && tp) {
61902
+ if (c.scopeOf) {
61903
+ var pOff = nodeOffsets[c.scopeOf] || { dx: 0, dy: 0 };
61904
+ c.el.setAttribute('d', computeConnectionPath(sp.cx - pOff.dx, sp.cy - pOff.dy, tp.cx - pOff.dx, tp.cy - pOff.dy));
61905
+ } else {
61906
+ c.el.setAttribute('d', computeConnectionPath(sp.cx, sp.cy, tp.cx, tp.cy));
61907
+ }
61908
+ }
61769
61909
  }
61770
61910
  });
61771
61911
  }
@@ -96590,7 +96730,7 @@ function displayInstalledPackage(pkg) {
96590
96730
  }
96591
96731
 
96592
96732
  // src/cli/index.ts
96593
- var version2 = true ? "0.10.1" : "0.0.0-dev";
96733
+ var version2 = true ? "0.10.2" : "0.0.0-dev";
96594
96734
  var program2 = new Command();
96595
96735
  program2.name("flow-weaver").description("Flow Weaver Annotations - Compile and validate workflow files").version(version2, "-v, --version", "Output the current version");
96596
96736
  program2.configureOutput({
@@ -481,7 +481,7 @@ path[data-source].port-hover { opacity: 1; }
481
481
  var connIndex = [];
482
482
  content.querySelectorAll('path[data-source]').forEach(function(p) {
483
483
  var src = p.getAttribute('data-source'), tgt = p.getAttribute('data-target');
484
- connIndex.push({ el: p, src: src, tgt: tgt, srcNode: src.split('.')[0], tgtNode: tgt.split('.')[0] });
484
+ connIndex.push({ el: p, src: src, tgt: tgt, srcNode: src.split('.')[0], tgtNode: tgt.split('.')[0], scopeOf: p.getAttribute('data-scope') || null });
485
485
  });
486
486
 
487
487
  // Snapshot of original port positions for reset
@@ -523,9 +523,18 @@ path[data-source].port-hover { opacity: 1; }
523
523
  off.dx += dx; off.dy += dy;
524
524
  var tr = 'translate(' + off.dx + ',' + off.dy + ')';
525
525
 
526
- // Move node group
526
+ // Move node group (if nested inside a scoped parent, subtract parent offset)
527
527
  var nodeG = content.querySelector('.nodes [data-node-id="' + CSS.escape(nodeId) + '"]');
528
- if (nodeG) nodeG.setAttribute('transform', tr);
528
+ if (nodeG) {
529
+ var parentNodeG = nodeG.parentElement ? nodeG.parentElement.closest('[data-node-id]') : null;
530
+ if (parentNodeG) {
531
+ var parentId = parentNodeG.getAttribute('data-node-id');
532
+ var parentOff = nodeOffsets[parentId] || { dx: 0, dy: 0 };
533
+ nodeG.setAttribute('transform', 'translate(' + (off.dx - parentOff.dx) + ',' + (off.dy - parentOff.dy) + ')');
534
+ } else {
535
+ nodeG.setAttribute('transform', tr);
536
+ }
537
+ }
529
538
 
530
539
  // Move label
531
540
  var labelG = content.querySelector('[data-label-for="' + CSS.escape(nodeId) + '"]');
@@ -572,11 +581,20 @@ path[data-source].port-hover { opacity: 1; }
572
581
  });
573
582
  }
574
583
 
575
- // Recalculate affected connection paths
584
+ // Recalculate affected connection paths (skip scope connections when parent is dragged — they move with the group transform)
576
585
  connIndex.forEach(function(c) {
586
+ if (c.scopeOf === nodeId) return;
577
587
  if (c.srcNode === nodeId || c.tgtNode === nodeId) {
578
588
  var sp = portPositions[c.src], tp = portPositions[c.tgt];
579
- if (sp && tp) c.el.setAttribute('d', computeConnectionPath(sp.cx, sp.cy, tp.cx, tp.cy));
589
+ if (sp && tp) {
590
+ if (c.scopeOf) {
591
+ // Scope connection paths live inside the parent group; use parent-local coords
592
+ var pOff = nodeOffsets[c.scopeOf] || { dx: 0, dy: 0 };
593
+ c.el.setAttribute('d', computeConnectionPath(sp.cx - pOff.dx, sp.cy - pOff.dy, tp.cx - pOff.dx, tp.cy - pOff.dy));
594
+ } else {
595
+ c.el.setAttribute('d', computeConnectionPath(sp.cx, sp.cy, tp.cx, tp.cy));
596
+ }
597
+ }
580
598
  }
581
599
  if (nodeG) {
582
600
  var children = nodeG.querySelectorAll(':scope > g[data-node-id]');
@@ -584,7 +602,14 @@ path[data-source].port-hover { opacity: 1; }
584
602
  var childId = childG.getAttribute('data-node-id');
585
603
  if (c.srcNode === childId || c.tgtNode === childId) {
586
604
  var sp = portPositions[c.src], tp = portPositions[c.tgt];
587
- if (sp && tp) c.el.setAttribute('d', computeConnectionPath(sp.cx, sp.cy, tp.cx, tp.cy));
605
+ if (sp && tp) {
606
+ if (c.scopeOf) {
607
+ var pOff = nodeOffsets[c.scopeOf] || { dx: 0, dy: 0 };
608
+ c.el.setAttribute('d', computeConnectionPath(sp.cx - pOff.dx, sp.cy - pOff.dy, tp.cx - pOff.dx, tp.cy - pOff.dy));
609
+ } else {
610
+ c.el.setAttribute('d', computeConnectionPath(sp.cx, sp.cy, tp.cx, tp.cy));
611
+ }
612
+ }
588
613
  }
589
614
  });
590
615
  }
@@ -100,12 +100,12 @@ function renderConnection(parts, conn, gradIndex) {
100
100
  const dashAttr = conn.isStepConnection ? '' : ' stroke-dasharray="8 4"';
101
101
  parts.push(` <path d="${conn.path}" fill="none" stroke="url(#conn-grad-${gradIndex})" stroke-width="3"${dashAttr} stroke-linecap="round" data-source="${escapeXml(conn.fromNode)}.${escapeXml(conn.fromPort)}:output" data-target="${escapeXml(conn.toNode)}.${escapeXml(conn.toPort)}:input"/>`);
102
102
  }
103
- function renderScopeConnection(parts, conn, allConnections) {
103
+ function renderScopeConnection(parts, conn, allConnections, parentNodeId) {
104
104
  const gradIndex = allConnections.indexOf(conn);
105
105
  if (gradIndex < 0)
106
106
  return;
107
107
  const dashAttr = conn.isStepConnection ? '' : ' stroke-dasharray="8 4"';
108
- parts.push(` <path d="${conn.path}" fill="none" stroke="url(#conn-grad-${gradIndex})" stroke-width="2.5"${dashAttr} stroke-linecap="round" data-source="${escapeXml(conn.fromNode)}.${escapeXml(conn.fromPort)}:output" data-target="${escapeXml(conn.toNode)}.${escapeXml(conn.toPort)}:input"/>`);
108
+ parts.push(` <path d="${conn.path}" fill="none" stroke="url(#conn-grad-${gradIndex})" stroke-width="2.5"${dashAttr} stroke-linecap="round" data-source="${escapeXml(conn.fromNode)}.${escapeXml(conn.fromPort)}:output" data-target="${escapeXml(conn.toNode)}.${escapeXml(conn.toPort)}:input" data-scope="${escapeXml(parentNodeId)}"/>`);
109
109
  }
110
110
  // ---- Node rendering ----
111
111
  /** Render node body rect + icon */
@@ -147,7 +147,7 @@ function renderScopedContent(parts, node, theme, themeName, allConnections) {
147
147
  parts.push(` <rect x="${scopeX}" y="${scopeY}" width="${scopeW}" height="${scopeH}" rx="4" fill="none" stroke="${theme.scopeAreaStroke}" stroke-width="1" stroke-dasharray="4 2" opacity="0.5"/>`);
148
148
  // Scope connections (before ports so ports appear on top)
149
149
  for (const conn of node.scopeConnections ?? []) {
150
- renderScopeConnection(parts, conn, allConnections);
150
+ renderScopeConnection(parts, conn, allConnections, node.id);
151
151
  }
152
152
  // Scope port dots (before children so dots sit on top of connections)
153
153
  if (scopePorts) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synergenius/flow-weaver",
3
- "version": "0.10.1",
3
+ "version": "0.10.2",
4
4
  "description": "Deterministic workflow compiler for AI agents. Compiles to standalone TypeScript, no runtime dependencies.",
5
5
  "private": false,
6
6
  "type": "module",
@@ -145,6 +145,7 @@
145
145
  "@types/js-yaml": "^4.0.9",
146
146
  "@types/node": "^20.11.0",
147
147
  "@types/react": "^19.0.0",
148
+ "@vitest/coverage-v8": "^4.0.18",
148
149
  "esbuild": "^0.27.2",
149
150
  "prettier": "^3.1.1",
150
151
  "rimraf": "6.1.2",