@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 +9 -3
- package/dist/cli/flow-weaver.mjs +79 -1
- package/dist/diagram/html-viewer.js +78 -0
- package/package.json +1 -1
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.**
|
|
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.**
|
|
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.**
|
|
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
|
package/dist/cli/flow-weaver.mjs
CHANGED
|
@@ -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.
|
|
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