@synergenius/flow-weaver 0.10.0 → 0.10.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.
package/README.md CHANGED
@@ -10,11 +10,17 @@ Design agent workflows in the Studio, in TypeScript, or let AI build them for yo
10
10
 
11
11
  ## Three Ways to Build
12
12
 
13
- **Studio.** Drag, drop, connect. The visual editor renders your workflow as an interactive graph with bidirectional sync: canvas changes write code, code changes update the canvas. 80+ plugins handle rendering, state, minimap, undo/redo, and more.
13
+ **Studio.**
14
+ A unified environment that combines a full code editor with a visual graph builder. You can write and refactor workflows directly in code or compose them visually on the canvas. Both representations stay synchronized at all times. Editing either one updates the other instantly, so you can move between abstraction levels without friction.
14
15
 
15
- **TypeScript.** Annotate plain functions with JSDoc tags. The compiler turns them into executable workflow graphs with full type safety, IDE autocomplete, and compile-time validation. No YAML, no JSON configs.
16
+ **TypeScript.**
17
+ Define workflows in plain TypeScript by annotating functions with JSDoc. The compiler derives an executable workflow graph with static typing and compile-time validation.
18
+ There is no YAML, no JSON configuration, and no runtime layer.
19
+ No lock-in. Remove the annotations and you keep a clean, readable TypeScript file with zero dependencies.
16
20
 
17
- **AI Agents.** Connect Claude Code, Cursor, or OpenClaw and they scaffold, validate, and ship workflows using 30+ MCP tools. The agent reads validation errors, fixes issues, and re-validates until the workflow compiles clean. The development loop (steps 1-4 are fully autonomous):
21
+ **AI Agents.**
22
+ Connect Claude Code, Cursor, or OpenClaw to design and ship workflows. Agents scaffold implementations, run the compiler, interpret validation errors, apply corrections, and repeat the process until the workflow compiles successfully.
23
+ With more than 30 MCP tools available, the entire build loop can run autonomously.
18
24
 
19
25
  1. **Agent creates**: scaffolds from templates, builds from a model, or writes from scratch
20
26
  2. **Compiler validates**: 15+ validation passes catch missing connections, type mismatches, unreachable paths
@@ -61351,6 +61351,21 @@ path[data-source].port-hover { opacity: 1; }
61351
61351
  border-radius: 3px; font-family: 'SF Mono', 'Fira Code', monospace;
61352
61352
  font-size: 12px; background: rgba(255,255,255,0.1);
61353
61353
  }
61354
+
61355
+ /* Studio nudge toast */
61356
+ #studio-hint {
61357
+ position: fixed; bottom: 60px; left: 50%;
61358
+ transform: translateX(-50%);
61359
+ background: ${surfaceMain}; border: 1px solid ${borderSubtle};
61360
+ padding: 8px 16px; border-radius: 8px;
61361
+ font-size: 13px; color: ${textMed};
61362
+ box-shadow: 0 2px 8px rgba(0,0,0,0.2);
61363
+ z-index: 20; opacity: 0; transition: opacity 0.4s;
61364
+ pointer-events: none;
61365
+ }
61366
+ #studio-hint.visible { opacity: 1; pointer-events: auto; }
61367
+ #studio-hint a { color: ${brandAccent}; text-decoration: none; font-weight: 600; }
61368
+ #studio-hint a:hover { text-decoration: underline; }
61354
61369
  </style>
61355
61370
  </head>
61356
61371
  <body>
@@ -61374,6 +61389,12 @@ path[data-source].port-hover { opacity: 1; }
61374
61389
  <path d="M1 5h12M1 9h12M5 1v12M9 1v12" opacity="0.4"/>
61375
61390
  </svg>
61376
61391
  </button>
61392
+ <button class="ctrl-btn" id="btn-reset" title="Reset layout" aria-label="Reset layout">
61393
+ <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" stroke-width="1.5">
61394
+ <path d="M1.5 2v3.5h3.5"/>
61395
+ <path d="M2.1 8.5a5 5 0 1 0 .9-4L1.5 5.5"/>
61396
+ </svg>
61397
+ </button>
61377
61398
  </div>
61378
61399
  <div id="info-panel">
61379
61400
  <h3 id="info-title"></h3>
@@ -61384,6 +61405,7 @@ path[data-source].port-hover { opacity: 1; }
61384
61405
  <span>Flow Weaver</span>
61385
61406
  </a>
61386
61407
  <div id="scroll-hint">Use <kbd id="mod-key">Ctrl</kbd> + scroll to zoom</div>
61408
+ <div id="studio-hint">Like rearranging? <a href="https://flowweaver.ai" target="_blank" rel="noopener">Flow Weaver Studio</a> saves your layouts.</div>
61387
61409
  <script>
61388
61410
  (function() {
61389
61411
  'use strict';
@@ -61396,6 +61418,7 @@ path[data-source].port-hover { opacity: 1; }
61396
61418
  var infoTitle = document.getElementById('info-title');
61397
61419
  var infoBody = document.getElementById('info-body');
61398
61420
  var scrollHint = document.getElementById('scroll-hint');
61421
+ var studioHint = document.getElementById('studio-hint');
61399
61422
 
61400
61423
  // Parse the original viewBox (diagram bounding box)
61401
61424
  var vbParts = '${viewBox}'.split(/\\s+/).map(Number);
@@ -61467,6 +61490,17 @@ path[data-source].port-hover { opacity: 1; }
61467
61490
 
61468
61491
  // ---- Pan (drag) + Node drag ----
61469
61492
  var draggedNodeId = null, dragNodeStart = null, didDragNode = false;
61493
+ var dragCount = 0, nudgeIndex = 0, nudgeTimer = null;
61494
+ var nudgeMessages = [
61495
+ 'Like rearranging? <a href="https://flowweaver.ai" target="_blank" rel="noopener">Flow Weaver Studio</a> saves your layouts.',
61496
+ 'Changes here are temporary. <a href="https://flowweaver.ai" target="_blank" rel="noopener">Try the Studio</a> to keep them.',
61497
+ 'Want to collaborate? <a href="https://flowweaver.ai" target="_blank" rel="noopener">Flow Weaver Studio</a> has real-time sharing.',
61498
+ 'Build and deploy from the cloud with <a href="https://flowweaver.ai" target="_blank" rel="noopener">Flow Weaver Studio</a>.',
61499
+ 'This viewer is read-only. <a href="https://flowweaver.ai" target="_blank" rel="noopener">Build workflows</a> in the Studio.',
61500
+ 'Version history, diff viewer, rollbacks. All in <a href="https://flowweaver.ai" target="_blank" rel="noopener">the Studio</a>.',
61501
+ 'Debug workflows step by step in <a href="https://flowweaver.ai" target="_blank" rel="noopener">Flow Weaver Studio</a>.',
61502
+ 'Ship faster. <a href="https://flowweaver.ai" target="_blank" rel="noopener">Flow Weaver Studio</a> runs your workflows in the cloud.'
61503
+ ];
61470
61504
 
61471
61505
  canvas.addEventListener('pointerdown', function(e) {
61472
61506
  if (e.button !== 0) return;
@@ -61525,6 +61559,18 @@ path[data-source].port-hover { opacity: 1; }
61525
61559
  });
61526
61560
 
61527
61561
  function endDrag() {
61562
+ if (didDragNode) {
61563
+ dragCount++;
61564
+ var threshold = nudgeIndex === 0 ? 3 : 5;
61565
+ if (dragCount >= threshold) {
61566
+ dragCount = 0;
61567
+ studioHint.innerHTML = nudgeMessages[nudgeIndex % nudgeMessages.length];
61568
+ nudgeIndex++;
61569
+ studioHint.classList.add('visible');
61570
+ clearTimeout(nudgeTimer);
61571
+ nudgeTimer = setTimeout(function() { studioHint.classList.remove('visible'); }, 5000);
61572
+ }
61573
+ }
61528
61574
  pointerDown = false;
61529
61575
  draggedNodeId = null;
61530
61576
  canvas.classList.remove('dragging');
@@ -61619,6 +61665,38 @@ path[data-source].port-hover { opacity: 1; }
61619
61665
  connIndex.push({ el: p, src: src, tgt: tgt, srcNode: src.split('.')[0], tgtNode: tgt.split('.')[0] });
61620
61666
  });
61621
61667
 
61668
+ // Snapshot of original port positions for reset
61669
+ var origPortPositions = {};
61670
+ for (var pid in portPositions) {
61671
+ origPortPositions[pid] = { cx: portPositions[pid].cx, cy: portPositions[pid].cy };
61672
+ }
61673
+
61674
+ function resetLayout() {
61675
+ for (var nid in nodeOffsets) {
61676
+ var esc = CSS.escape(nid);
61677
+ var nodeG = content.querySelector('.nodes [data-node-id="' + esc + '"]');
61678
+ if (nodeG) nodeG.removeAttribute('transform');
61679
+ var labelG = content.querySelector('[data-label-for="' + esc + '"]');
61680
+ if (labelG) labelG.removeAttribute('transform');
61681
+ allLabelIds.forEach(function(id) {
61682
+ if (id.indexOf(nid + '.') === 0) {
61683
+ var el = labelMap[id];
61684
+ if (el) el.removeAttribute('transform');
61685
+ }
61686
+ });
61687
+ }
61688
+ nodeOffsets = {};
61689
+ for (var pid in origPortPositions) {
61690
+ portPositions[pid] = { cx: origPortPositions[pid].cx, cy: origPortPositions[pid].cy };
61691
+ }
61692
+ connIndex.forEach(function(c) {
61693
+ var sp = portPositions[c.src], tp = portPositions[c.tgt];
61694
+ if (sp && tp) c.el.setAttribute('d', computeConnectionPath(sp.cx, sp.cy, tp.cx, tp.cy));
61695
+ });
61696
+ fitToView();
61697
+ }
61698
+ document.getElementById('btn-reset').addEventListener('click', resetLayout);
61699
+
61622
61700
  // ---- Node drag: moveNode ----
61623
61701
  function moveNode(nodeId, dx, dy) {
61624
61702
  if (!nodeOffsets[nodeId]) nodeOffsets[nodeId] = { dx: 0, dy: 0 };
@@ -96512,7 +96590,7 @@ function displayInstalledPackage(pkg) {
96512
96590
  }
96513
96591
 
96514
96592
  // src/cli/index.ts
96515
- var version2 = true ? "0.10.0" : "0.0.0-dev";
96593
+ var version2 = true ? "0.10.1" : "0.0.0-dev";
96516
96594
  var program2 = new Command();
96517
96595
  program2.name("flow-weaver").description("Flow Weaver Annotations - Compile and validate workflow files").version(version2, "-v, --version", "Output the current version");
96518
96596
  program2.configureOutput({
@@ -170,6 +170,21 @@ path[data-source].port-hover { opacity: 1; }
170
170
  border-radius: 3px; font-family: 'SF Mono', 'Fira Code', monospace;
171
171
  font-size: 12px; background: rgba(255,255,255,0.1);
172
172
  }
173
+
174
+ /* Studio nudge toast */
175
+ #studio-hint {
176
+ position: fixed; bottom: 60px; left: 50%;
177
+ transform: translateX(-50%);
178
+ background: ${surfaceMain}; border: 1px solid ${borderSubtle};
179
+ padding: 8px 16px; border-radius: 8px;
180
+ font-size: 13px; color: ${textMed};
181
+ box-shadow: 0 2px 8px rgba(0,0,0,0.2);
182
+ z-index: 20; opacity: 0; transition: opacity 0.4s;
183
+ pointer-events: none;
184
+ }
185
+ #studio-hint.visible { opacity: 1; pointer-events: auto; }
186
+ #studio-hint a { color: ${brandAccent}; text-decoration: none; font-weight: 600; }
187
+ #studio-hint a:hover { text-decoration: underline; }
173
188
  </style>
174
189
  </head>
175
190
  <body>
@@ -193,6 +208,12 @@ path[data-source].port-hover { opacity: 1; }
193
208
  <path d="M1 5h12M1 9h12M5 1v12M9 1v12" opacity="0.4"/>
194
209
  </svg>
195
210
  </button>
211
+ <button class="ctrl-btn" id="btn-reset" title="Reset layout" aria-label="Reset layout">
212
+ <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" stroke-width="1.5">
213
+ <path d="M1.5 2v3.5h3.5"/>
214
+ <path d="M2.1 8.5a5 5 0 1 0 .9-4L1.5 5.5"/>
215
+ </svg>
216
+ </button>
196
217
  </div>
197
218
  <div id="info-panel">
198
219
  <h3 id="info-title"></h3>
@@ -203,6 +224,7 @@ path[data-source].port-hover { opacity: 1; }
203
224
  <span>Flow Weaver</span>
204
225
  </a>
205
226
  <div id="scroll-hint">Use <kbd id="mod-key">Ctrl</kbd> + scroll to zoom</div>
227
+ <div id="studio-hint">Like rearranging? <a href="https://flowweaver.ai" target="_blank" rel="noopener">Flow Weaver Studio</a> saves your layouts.</div>
206
228
  <script>
207
229
  (function() {
208
230
  'use strict';
@@ -215,6 +237,7 @@ path[data-source].port-hover { opacity: 1; }
215
237
  var infoTitle = document.getElementById('info-title');
216
238
  var infoBody = document.getElementById('info-body');
217
239
  var scrollHint = document.getElementById('scroll-hint');
240
+ var studioHint = document.getElementById('studio-hint');
218
241
 
219
242
  // Parse the original viewBox (diagram bounding box)
220
243
  var vbParts = '${viewBox}'.split(/\\s+/).map(Number);
@@ -286,6 +309,17 @@ path[data-source].port-hover { opacity: 1; }
286
309
 
287
310
  // ---- Pan (drag) + Node drag ----
288
311
  var draggedNodeId = null, dragNodeStart = null, didDragNode = false;
312
+ var dragCount = 0, nudgeIndex = 0, nudgeTimer = null;
313
+ var nudgeMessages = [
314
+ 'Like rearranging? <a href="https://flowweaver.ai" target="_blank" rel="noopener">Flow Weaver Studio</a> saves your layouts.',
315
+ 'Changes here are temporary. <a href="https://flowweaver.ai" target="_blank" rel="noopener">Try the Studio</a> to keep them.',
316
+ 'Want to collaborate? <a href="https://flowweaver.ai" target="_blank" rel="noopener">Flow Weaver Studio</a> has real-time sharing.',
317
+ 'Build and deploy from the cloud with <a href="https://flowweaver.ai" target="_blank" rel="noopener">Flow Weaver Studio</a>.',
318
+ 'This viewer is read-only. <a href="https://flowweaver.ai" target="_blank" rel="noopener">Build workflows</a> in the Studio.',
319
+ 'Version history, diff viewer, rollbacks. All in <a href="https://flowweaver.ai" target="_blank" rel="noopener">the Studio</a>.',
320
+ 'Debug workflows step by step in <a href="https://flowweaver.ai" target="_blank" rel="noopener">Flow Weaver Studio</a>.',
321
+ 'Ship faster. <a href="https://flowweaver.ai" target="_blank" rel="noopener">Flow Weaver Studio</a> runs your workflows in the cloud.'
322
+ ];
289
323
 
290
324
  canvas.addEventListener('pointerdown', function(e) {
291
325
  if (e.button !== 0) return;
@@ -344,6 +378,18 @@ path[data-source].port-hover { opacity: 1; }
344
378
  });
345
379
 
346
380
  function endDrag() {
381
+ if (didDragNode) {
382
+ dragCount++;
383
+ var threshold = nudgeIndex === 0 ? 3 : 5;
384
+ if (dragCount >= threshold) {
385
+ dragCount = 0;
386
+ studioHint.innerHTML = nudgeMessages[nudgeIndex % nudgeMessages.length];
387
+ nudgeIndex++;
388
+ studioHint.classList.add('visible');
389
+ clearTimeout(nudgeTimer);
390
+ nudgeTimer = setTimeout(function() { studioHint.classList.remove('visible'); }, 5000);
391
+ }
392
+ }
347
393
  pointerDown = false;
348
394
  draggedNodeId = null;
349
395
  canvas.classList.remove('dragging');
@@ -438,6 +484,38 @@ path[data-source].port-hover { opacity: 1; }
438
484
  connIndex.push({ el: p, src: src, tgt: tgt, srcNode: src.split('.')[0], tgtNode: tgt.split('.')[0] });
439
485
  });
440
486
 
487
+ // Snapshot of original port positions for reset
488
+ var origPortPositions = {};
489
+ for (var pid in portPositions) {
490
+ origPortPositions[pid] = { cx: portPositions[pid].cx, cy: portPositions[pid].cy };
491
+ }
492
+
493
+ function resetLayout() {
494
+ for (var nid in nodeOffsets) {
495
+ var esc = CSS.escape(nid);
496
+ var nodeG = content.querySelector('.nodes [data-node-id="' + esc + '"]');
497
+ if (nodeG) nodeG.removeAttribute('transform');
498
+ var labelG = content.querySelector('[data-label-for="' + esc + '"]');
499
+ if (labelG) labelG.removeAttribute('transform');
500
+ allLabelIds.forEach(function(id) {
501
+ if (id.indexOf(nid + '.') === 0) {
502
+ var el = labelMap[id];
503
+ if (el) el.removeAttribute('transform');
504
+ }
505
+ });
506
+ }
507
+ nodeOffsets = {};
508
+ for (var pid in origPortPositions) {
509
+ portPositions[pid] = { cx: origPortPositions[pid].cx, cy: origPortPositions[pid].cy };
510
+ }
511
+ connIndex.forEach(function(c) {
512
+ var sp = portPositions[c.src], tp = portPositions[c.tgt];
513
+ if (sp && tp) c.el.setAttribute('d', computeConnectionPath(sp.cx, sp.cy, tp.cx, tp.cy));
514
+ });
515
+ fitToView();
516
+ }
517
+ document.getElementById('btn-reset').addEventListener('click', resetLayout);
518
+
441
519
  // ---- Node drag: moveNode ----
442
520
  function moveNode(nodeId, dx, dy) {
443
521
  if (!nodeOffsets[nodeId]) nodeOffsets[nodeId] = { dx: 0, dy: 0 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synergenius/flow-weaver",
3
- "version": "0.10.0",
3
+ "version": "0.10.1",
4
4
  "description": "Deterministic workflow compiler for AI agents. Compiles to standalone TypeScript, no runtime dependencies.",
5
5
  "private": false,
6
6
  "type": "module",