@synergenius/flow-weaver 0.13.1 → 0.13.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 +85 -65
- package/dist/cli/flow-weaver.mjs +29 -2
- package/dist/diagram/geometry.js +47 -0
- package/dist/generated-version.d.ts +1 -1
- package/dist/generated-version.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Flow Weaver
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@synergenius/flow-weaver)
|
|
4
4
|
[](https://www.npmjs.com/package/@synergenius/flow-weaver)
|
|
@@ -10,34 +10,43 @@
|
|
|
10
10
|
|
|
11
11
|
**Build AI agent workflows visually. Ship them as your own code.**
|
|
12
12
|
|
|
13
|
-
Design agent workflows in the Studio, in TypeScript, or let AI build them for you.
|
|
13
|
+
Design agent workflows in the Studio, in TypeScript, or let AI build them for you. The compiler validates everything with 20+ rule categories. The output is standalone TypeScript you deploy anywhere, zero runtime dependency on Flow Weaver.
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
**Studio.**
|
|
18
|
-
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.
|
|
15
|
+
[**flowweaver.ai**](https://flowweaver.ai) · [**Open the Studio**](https://flowweaver.ai/studio) · [**Docs**](https://flowweaver.ai/docs) · [**Discord**](https://discord.gg/6Byh3ur2bk) · [**npm**](https://www.npmjs.com/package/@synergenius/flow-weaver)
|
|
19
16
|
|
|
20
|
-
|
|
21
|
-
Define workflows in plain TypeScript by annotating functions with JSDoc. The compiler derives an executable workflow graph with static typing and compile-time validation.
|
|
22
|
-
There is no YAML, no JSON configuration, and no runtime layer.
|
|
23
|
-
No lock-in. Remove the annotations and you keep a clean, readable TypeScript file with zero dependencies.
|
|
17
|
+
---
|
|
24
18
|
|
|
25
|
-
|
|
26
|
-
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.
|
|
27
|
-
With more than 30 MCP tools available, the entire build loop can run autonomously.
|
|
19
|
+
## Try It
|
|
28
20
|
|
|
29
|
-
|
|
30
|
-
2. **Compiler validates**: 15+ validation passes catch missing connections, type mismatches, unreachable paths
|
|
31
|
-
3. **Agent iterates**: validation errors include fix suggestions, the agent corrects and re-validates
|
|
32
|
-
4. **Agent tests**: deterministic mock providers for reproducible testing without real API calls
|
|
33
|
-
5. **Human reviews**: visual editor or SVG diagram for final approval
|
|
21
|
+
**In the browser.** Open the [Cloud Studio](https://flowweaver.ai/studio), sign up, and start building. No install required.
|
|
34
22
|
|
|
35
|
-
|
|
23
|
+
**From the terminal.**
|
|
36
24
|
|
|
37
25
|
```bash
|
|
38
26
|
npm install @synergenius/flow-weaver
|
|
27
|
+
npx flow-weaver init my-project
|
|
28
|
+
cd my-project
|
|
29
|
+
npx flow-weaver run workflows/example.ts --params '{"input": "value"}'
|
|
39
30
|
```
|
|
40
31
|
|
|
32
|
+
## How It Works
|
|
33
|
+
|
|
34
|
+
**Generate.** AI agents build workflows via 48 MCP tools, or you build visually in the Studio, or you write annotated TypeScript by hand. All three stay in sync.
|
|
35
|
+
|
|
36
|
+
**Validate.** The compiler catches wiring errors, type mismatches, missing handlers, unreachable paths, and agent-specific mistakes before anything runs. Not at runtime, not in production.
|
|
37
|
+
|
|
38
|
+
**Own.** Compiled output is plain TypeScript with zero imports from Flow Weaver. Clean git diffs, standard testing, no license obligations on the output. If Flow Weaver disappeared tomorrow, your agents would still run.
|
|
39
|
+
|
|
40
|
+
## Three Ways to Build
|
|
41
|
+
|
|
42
|
+
**Studio.** A visual IDE that combines a full code editor with a graph builder. Write and refactor workflows in code or compose them on the canvas. Both representations stay synchronized: editing either one updates the other instantly.
|
|
43
|
+
|
|
44
|
+
**TypeScript.** Define workflows in plain TypeScript by annotating functions with JSDoc. The compiler derives an executable workflow graph with static typing and compile-time validation. No YAML, no JSON configuration, no runtime layer. Remove the annotations and you keep a clean TypeScript file with zero dependencies.
|
|
45
|
+
|
|
46
|
+
**AI Agents.** Connect Claude Code, Cursor, or OpenClaw and let agents scaffold implementations, run the compiler, interpret validation errors, apply corrections, and iterate until the workflow compiles. Agents then test with deterministic mock providers and generate diagrams for human review.
|
|
47
|
+
|
|
48
|
+
## Quick Start
|
|
49
|
+
|
|
41
50
|
Workflows are plain TypeScript. Annotations declare the graph structure:
|
|
42
51
|
|
|
43
52
|
```typescript
|
|
@@ -79,7 +88,7 @@ The compiler fills in the function body while preserving your code outside the g
|
|
|
79
88
|
|
|
80
89
|
## AI-Native Development with MCP
|
|
81
90
|
|
|
82
|
-
Flow Weaver includes an MCP server for Claude Code, Cursor, OpenClaw, or any MCP-compatible agent:
|
|
91
|
+
Flow Weaver includes an MCP server with 48 tools for Claude Code, Cursor, OpenClaw, or any MCP-compatible agent:
|
|
83
92
|
|
|
84
93
|
```bash
|
|
85
94
|
npx flow-weaver mcp-server # auto-registers with Claude Code
|
|
@@ -108,27 +117,20 @@ npx flow-weaver status my-workflow.ts # shows stub vs implemented progress
|
|
|
108
117
|
npx flow-weaver implement my-workflow.ts processData # scaffolds a node body
|
|
109
118
|
```
|
|
110
119
|
|
|
111
|
-
The graph is valid before any node has a real implementation. Fill in node bodies incrementally, check `status` to track progress.
|
|
120
|
+
The graph is valid before any node has a real implementation. Fill in node bodies incrementally, check `status` to track progress. The architect defines the shape, developers fill in the logic.
|
|
112
121
|
|
|
113
122
|
## Agent Workflow Templates
|
|
114
123
|
|
|
115
|
-
Built-in templates for AI agent workflows
|
|
124
|
+
Built-in templates for AI agent workflows:
|
|
116
125
|
|
|
117
126
|
```bash
|
|
118
|
-
# Scaffold a tool-calling agent with memory and error handling
|
|
119
127
|
npx flow-weaver create workflow ai-agent my-agent.ts --provider openai --model gpt-4o
|
|
120
|
-
|
|
121
|
-
# ReAct pattern (Thought -> Action -> Observation loop)
|
|
122
128
|
npx flow-weaver create workflow ai-react react-agent.ts
|
|
123
|
-
|
|
124
|
-
# RAG pipeline (Retrieve -> Augment -> Generate)
|
|
125
129
|
npx flow-weaver create workflow ai-rag rag-pipeline.ts
|
|
126
|
-
|
|
127
|
-
# Durable agent with per-step retries (compiles to Inngest)
|
|
128
130
|
npx flow-weaver create workflow ai-agent-durable durable-agent.ts
|
|
129
131
|
```
|
|
130
132
|
|
|
131
|
-
**12 workflow templates
|
|
133
|
+
**12 workflow templates:**
|
|
132
134
|
|
|
133
135
|
| Template | What it builds |
|
|
134
136
|
|----------|---------------|
|
|
@@ -145,9 +147,9 @@ npx flow-weaver create workflow ai-agent-durable durable-agent.ts
|
|
|
145
147
|
| `webhook` | HTTP event handler |
|
|
146
148
|
| `error-handler` | Error recovery pattern |
|
|
147
149
|
|
|
148
|
-
**12 node templates** for common
|
|
150
|
+
Plus **12 node templates** for common building blocks: `llm-call`, `tool-executor`, `conversation-memory`, `prompt-template`, `json-extractor`, `human-approval`, `agent-router`, `rag-retriever`, `validator`, `transformer`, `http`, `aggregator`.
|
|
149
151
|
|
|
150
|
-
##
|
|
152
|
+
## Compile-Time Validation
|
|
151
153
|
|
|
152
154
|
The validator understands AI agent patterns and enforces safety rules:
|
|
153
155
|
|
|
@@ -159,7 +161,7 @@ AGENT_LLM_NO_FALLBACK LLM failure goes directly to Exit, add retry
|
|
|
159
161
|
AGENT_TOOL_NO_OUTPUT_HANDLING Tool executor outputs are all unconnected, results are discarded
|
|
160
162
|
```
|
|
161
163
|
|
|
162
|
-
These
|
|
164
|
+
These are not generic lint rules. The validator identifies LLM, tool-executor, human-approval, and memory nodes by port signatures, annotations, and naming patterns, then applies agent-specific checks.
|
|
163
165
|
|
|
164
166
|
## Deterministic Agent Testing
|
|
165
167
|
|
|
@@ -185,9 +187,9 @@ const replay = loadRecording('fixtures/agent-session.json');
|
|
|
185
187
|
|
|
186
188
|
Mock human approvals, fast-forward delays, and simulate external events. Configured via `globalThis.__fw_mock_config__`.
|
|
187
189
|
|
|
188
|
-
## Scoped Ports: Agent Loops Without Cycles
|
|
190
|
+
## Scoped Ports: Agent Loops Without Graph Cycles
|
|
189
191
|
|
|
190
|
-
Most workflow engines either ban loops (DAG-only) or allow arbitrary cycles
|
|
192
|
+
Most workflow engines either ban loops entirely (DAG-only) or allow arbitrary cycles that are hard to reason about. Flow Weaver takes a third path: **scoped ports** express iteration while keeping the graph acyclic and statically analyzable.
|
|
191
193
|
|
|
192
194
|
```typescript
|
|
193
195
|
/**
|
|
@@ -202,32 +204,9 @@ Most workflow engines either ban loops (DAG-only) or allow arbitrary cycles (har
|
|
|
202
204
|
*/
|
|
203
205
|
```
|
|
204
206
|
|
|
205
|
-
The scope's output ports become callback parameters, and input ports become return values. Agent reasoning loops, ForEach over collections, map/reduce patterns, nested sub-workflows
|
|
206
|
-
|
|
207
|
-
## Diagram Generation
|
|
208
|
-
|
|
209
|
-
Generate SVG or interactive HTML diagrams from any workflow:
|
|
210
|
-
|
|
211
|
-
```bash
|
|
212
|
-
flow-weaver diagram workflow.ts -o workflow.svg --theme dark
|
|
213
|
-
flow-weaver diagram workflow.ts -o workflow.html --format html
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
Customize node appearance with annotations:
|
|
217
|
-
|
|
218
|
-
```typescript
|
|
219
|
-
/**
|
|
220
|
-
* @flowWeaver nodeType
|
|
221
|
-
* @color blue
|
|
222
|
-
* @icon database
|
|
223
|
-
*/
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
Named colors: `blue`, `purple`, `green`, `cyan`, `orange`, `pink`, `red`, `yellow`. Icons include `api`, `database`, `shield`, `brain`, `cloud`, `search`, `code`, and 60+ more from Material Design 3.
|
|
227
|
-
|
|
228
|
-
The interactive HTML viewer supports zoom/pan, click-to-inspect nodes, port-level hover with connection tracing, and works standalone or embedded in an iframe.
|
|
207
|
+
The scope's output ports become callback parameters, and input ports become return values. Agent reasoning loops, ForEach over collections, map/reduce patterns, and nested sub-workflows all work without introducing graph cycles.
|
|
229
208
|
|
|
230
|
-
##
|
|
209
|
+
## Deploy Anywhere
|
|
231
210
|
|
|
232
211
|
Same workflow source, multiple deployment targets:
|
|
233
212
|
|
|
@@ -249,6 +228,27 @@ flow-weaver serve ./workflows --port 3000 --swagger
|
|
|
249
228
|
|
|
250
229
|
Both the default TypeScript target and Inngest target parallelize independent nodes with `Promise.all()`. Inngest additionally wraps each node in `step.run()` for individual durability and generates typed Zod event schemas.
|
|
251
230
|
|
|
231
|
+
## Diagram Generation
|
|
232
|
+
|
|
233
|
+
Generate SVG or interactive HTML diagrams from any workflow:
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
flow-weaver diagram workflow.ts -o workflow.svg --theme dark
|
|
237
|
+
flow-weaver diagram workflow.ts -o workflow.html --format html
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Customize node appearance with annotations:
|
|
241
|
+
|
|
242
|
+
```typescript
|
|
243
|
+
/**
|
|
244
|
+
* @flowWeaver nodeType
|
|
245
|
+
* @color blue
|
|
246
|
+
* @icon database
|
|
247
|
+
*/
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
Named colors: `blue`, `purple`, `green`, `cyan`, `orange`, `pink`, `red`, `yellow`. Icons include `api`, `database`, `shield`, `brain`, `cloud`, `search`, `code`, and 60+ more from Material Design 3. The interactive HTML viewer supports zoom/pan, click-to-inspect nodes, and port-level hover with connection tracing.
|
|
251
|
+
|
|
252
252
|
## API
|
|
253
253
|
|
|
254
254
|
```typescript
|
|
@@ -370,18 +370,38 @@ function nodeName(
|
|
|
370
370
|
|
|
371
371
|
Expression nodes (`@expression`) skip the control flow boilerplate. Inputs and outputs map directly to the TypeScript signature.
|
|
372
372
|
|
|
373
|
-
##
|
|
373
|
+
## Flow Weaver Cloud
|
|
374
374
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
375
|
+
[flowweaver.ai](https://flowweaver.ai) is the hosted platform that adds collaboration, managed deployments, and team features on top of everything the CLI provides.
|
|
376
|
+
|
|
377
|
+
What the cloud adds:
|
|
378
|
+
|
|
379
|
+
- **Browser-based Studio** with real-time collaborative editing
|
|
380
|
+
- **One-click deployment** of any workflow as an HTTP endpoint
|
|
381
|
+
- **Execution logs** for every workflow run, with input/output history
|
|
382
|
+
- **Visual debugger** for step-through node inspection (Pro)
|
|
383
|
+
- **Version history** and workflow snapshots (Pro)
|
|
384
|
+
- **AI Chat assistant** for building and debugging workflows (Pro)
|
|
385
|
+
- **Organization workspaces** with team management (Business)
|
|
386
|
+
|
|
387
|
+
Three tiers: **Free** (3 workflows, 1 deployment, 100 executions/month), **Pro** at 9 EUR/month (25 workflows, 10k executions), and **Business** at 29 EUR/month (unlimited workflows, 100k executions). See [flowweaver.ai/pricing](https://flowweaver.ai/pricing) for details.
|
|
388
|
+
|
|
389
|
+
The CLI remains fully functional for local development. The cloud adds the parts that are hard to do alone: team collaboration, always-on endpoints, and operational visibility.
|
|
390
|
+
|
|
391
|
+
## Community
|
|
392
|
+
|
|
393
|
+
- [Discord](https://discord.gg/6Byh3ur2bk)
|
|
394
|
+
- [GitHub Discussions](https://github.com/synergenius-fw/flow-weaver/discussions)
|
|
395
|
+
- [X / Twitter](https://x.com/flowweaver_ai)
|
|
396
|
+
- [Website](https://flowweaver.ai)
|
|
379
397
|
|
|
380
398
|
## Development
|
|
381
399
|
|
|
382
400
|
```bash
|
|
383
401
|
npm run build # Build
|
|
384
402
|
npm run watch # Watch mode
|
|
403
|
+
npm test # Run all tests
|
|
404
|
+
npm run test:watch # Watch mode
|
|
385
405
|
npm run typecheck # Type check
|
|
386
406
|
npm run docs # Generate API docs
|
|
387
407
|
```
|
package/dist/cli/flow-weaver.mjs
CHANGED
|
@@ -9671,7 +9671,7 @@ var VERSION;
|
|
|
9671
9671
|
var init_generated_version = __esm({
|
|
9672
9672
|
"src/generated-version.ts"() {
|
|
9673
9673
|
"use strict";
|
|
9674
|
-
VERSION = "0.13.
|
|
9674
|
+
VERSION = "0.13.2";
|
|
9675
9675
|
}
|
|
9676
9676
|
});
|
|
9677
9677
|
|
|
@@ -46774,6 +46774,8 @@ function buildScopeSubGraph(parentNode, parentNt, scopeName, childIds, ast, node
|
|
|
46774
46774
|
if (!childInst) continue;
|
|
46775
46775
|
const childNode = buildInstanceNode(childId, childInst.nodeType, childInst.config, nodeTypeMap, theme);
|
|
46776
46776
|
computeNodeDimensions(childNode);
|
|
46777
|
+
if (childInst.config?.width != null) childNode.width = childInst.config.width;
|
|
46778
|
+
if (childInst.config?.height != null) childNode.height = childInst.config.height;
|
|
46777
46779
|
children.push(childNode);
|
|
46778
46780
|
childNodeMap.set(childId, childNode);
|
|
46779
46781
|
}
|
|
@@ -47087,6 +47089,23 @@ function resolveHorizontalOverlaps(diagramNodes, explicitPositions) {
|
|
|
47087
47089
|
}
|
|
47088
47090
|
}
|
|
47089
47091
|
}
|
|
47092
|
+
function resolvePostLayoutOverlaps(diagramNodes) {
|
|
47093
|
+
const hasScopeParent = [...diagramNodes.values()].some((n) => n.scopeChildren && n.scopeChildren.length > 0);
|
|
47094
|
+
if (!hasScopeParent) return;
|
|
47095
|
+
const nodes = [...diagramNodes.values()].sort((a, b) => a.x - b.x);
|
|
47096
|
+
for (let i = 1; i < nodes.length; i++) {
|
|
47097
|
+
const prev = nodes[i - 1];
|
|
47098
|
+
const curr = nodes[i];
|
|
47099
|
+
if (!prev.scopeChildren || prev.scopeChildren.length === 0) continue;
|
|
47100
|
+
const actualGap = curr.x - (prev.x + prev.width);
|
|
47101
|
+
if (actualGap < MIN_EDGE_GAP) {
|
|
47102
|
+
const shift = MIN_EDGE_GAP - actualGap;
|
|
47103
|
+
for (let j = i; j < nodes.length; j++) {
|
|
47104
|
+
nodes[j].x += shift;
|
|
47105
|
+
}
|
|
47106
|
+
}
|
|
47107
|
+
}
|
|
47108
|
+
}
|
|
47090
47109
|
function buildDiagramGraph(ast, options = {}) {
|
|
47091
47110
|
const themeName = options.theme ?? "dark";
|
|
47092
47111
|
const nodeTypeMap = /* @__PURE__ */ new Map();
|
|
@@ -47184,6 +47203,13 @@ function buildDiagramGraph(ast, options = {}) {
|
|
|
47184
47203
|
if (!parentNt) continue;
|
|
47185
47204
|
buildScopeSubGraph(parentNode, parentNt, scopeName, childIds, ast, nodeTypeMap, themeName);
|
|
47186
47205
|
}
|
|
47206
|
+
for (const inst of ast.instances) {
|
|
47207
|
+
if (scopedChildren.has(inst.id)) continue;
|
|
47208
|
+
const node = diagramNodes.get(inst.id);
|
|
47209
|
+
if (!node) continue;
|
|
47210
|
+
if (inst.config?.width != null) node.width = inst.config.width;
|
|
47211
|
+
if (inst.config?.height != null) node.height = inst.config.height;
|
|
47212
|
+
}
|
|
47187
47213
|
const explicitPositions = extractExplicitPositions(ast);
|
|
47188
47214
|
const allPositioned = [...diagramNodes.keys()].every((id) => explicitPositions.has(id));
|
|
47189
47215
|
const nonePositioned = ![...diagramNodes.keys()].some((id) => explicitPositions.has(id));
|
|
@@ -47203,6 +47229,7 @@ function buildDiagramGraph(ast, options = {}) {
|
|
|
47203
47229
|
assignUnpositionedNodes(layers, diagramNodes, explicitPositions);
|
|
47204
47230
|
resolveHorizontalOverlaps(diagramNodes, explicitPositions);
|
|
47205
47231
|
}
|
|
47232
|
+
resolvePostLayoutOverlaps(diagramNodes);
|
|
47206
47233
|
for (const node of diagramNodes.values()) {
|
|
47207
47234
|
computePortPositions(node);
|
|
47208
47235
|
}
|
|
@@ -110075,7 +110102,7 @@ async function mcpSetupCommand(options, deps) {
|
|
|
110075
110102
|
|
|
110076
110103
|
// src/cli/index.ts
|
|
110077
110104
|
init_error_utils();
|
|
110078
|
-
var version2 = true ? "0.13.
|
|
110105
|
+
var version2 = true ? "0.13.2" : "0.0.0-dev";
|
|
110079
110106
|
var program2 = new Command();
|
|
110080
110107
|
program2.name("flow-weaver").description("Flow Weaver Annotations - Compile and validate workflow files").version(version2, "-v, --version", "Output the current version");
|
|
110081
110108
|
program2.configureOutput({
|
package/dist/diagram/geometry.js
CHANGED
|
@@ -298,6 +298,10 @@ function buildScopeSubGraph(parentNode, parentNt, scopeName, childIds, ast, node
|
|
|
298
298
|
continue;
|
|
299
299
|
const childNode = buildInstanceNode(childId, childInst.nodeType, childInst.config, nodeTypeMap, theme);
|
|
300
300
|
computeNodeDimensions(childNode);
|
|
301
|
+
if (childInst.config?.width != null)
|
|
302
|
+
childNode.width = childInst.config.width;
|
|
303
|
+
if (childInst.config?.height != null)
|
|
304
|
+
childNode.height = childInst.config.height;
|
|
301
305
|
children.push(childNode);
|
|
302
306
|
childNodeMap.set(childId, childNode);
|
|
303
307
|
}
|
|
@@ -628,6 +632,32 @@ function resolveHorizontalOverlaps(diagramNodes, explicitPositions) {
|
|
|
628
632
|
}
|
|
629
633
|
}
|
|
630
634
|
}
|
|
635
|
+
/**
|
|
636
|
+
* After all positioning, resolve overlaps caused by expanded scope boxes.
|
|
637
|
+
* Only checks nodes immediately after a scope parent — regular node spacing
|
|
638
|
+
* is left to the user's explicit positions. When a node falls inside the
|
|
639
|
+
* expanded scope box, shift it and all further-right nodes to clear.
|
|
640
|
+
*/
|
|
641
|
+
function resolvePostLayoutOverlaps(diagramNodes) {
|
|
642
|
+
const hasScopeParent = [...diagramNodes.values()].some(n => n.scopeChildren && n.scopeChildren.length > 0);
|
|
643
|
+
if (!hasScopeParent)
|
|
644
|
+
return;
|
|
645
|
+
const nodes = [...diagramNodes.values()].sort((a, b) => a.x - b.x);
|
|
646
|
+
for (let i = 1; i < nodes.length; i++) {
|
|
647
|
+
const prev = nodes[i - 1];
|
|
648
|
+
const curr = nodes[i];
|
|
649
|
+
// Only resolve overlaps caused by scope parent expansion
|
|
650
|
+
if (!prev.scopeChildren || prev.scopeChildren.length === 0)
|
|
651
|
+
continue;
|
|
652
|
+
const actualGap = curr.x - (prev.x + prev.width);
|
|
653
|
+
if (actualGap < MIN_EDGE_GAP) {
|
|
654
|
+
const shift = MIN_EDGE_GAP - actualGap;
|
|
655
|
+
for (let j = i; j < nodes.length; j++) {
|
|
656
|
+
nodes[j].x += shift;
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
}
|
|
631
661
|
// ---- Main orchestrator ----
|
|
632
662
|
export function buildDiagramGraph(ast, options = {}) {
|
|
633
663
|
const themeName = options.theme ?? 'dark';
|
|
@@ -741,6 +771,18 @@ export function buildDiagramGraph(ast, options = {}) {
|
|
|
741
771
|
continue;
|
|
742
772
|
buildScopeSubGraph(parentNode, parentNt, scopeName, childIds, ast, nodeTypeMap, themeName);
|
|
743
773
|
}
|
|
774
|
+
// Apply explicit [size: W H] annotation — hard override (not a floor)
|
|
775
|
+
for (const inst of ast.instances) {
|
|
776
|
+
if (scopedChildren.has(inst.id))
|
|
777
|
+
continue;
|
|
778
|
+
const node = diagramNodes.get(inst.id);
|
|
779
|
+
if (!node)
|
|
780
|
+
continue;
|
|
781
|
+
if (inst.config?.width != null)
|
|
782
|
+
node.width = inst.config.width;
|
|
783
|
+
if (inst.config?.height != null)
|
|
784
|
+
node.height = inst.config.height;
|
|
785
|
+
}
|
|
744
786
|
// Layout — use explicit positions when available, auto-layout otherwise
|
|
745
787
|
const explicitPositions = extractExplicitPositions(ast);
|
|
746
788
|
const allPositioned = [...diagramNodes.keys()].every(id => explicitPositions.has(id));
|
|
@@ -766,6 +808,11 @@ export function buildDiagramGraph(ast, options = {}) {
|
|
|
766
808
|
assignUnpositionedNodes(layers, diagramNodes, explicitPositions);
|
|
767
809
|
resolveHorizontalOverlaps(diagramNodes, explicitPositions);
|
|
768
810
|
}
|
|
811
|
+
// Resolve overlaps caused by expanded scope boxes. When all positions are
|
|
812
|
+
// explicit, resolveHorizontalOverlaps is never called (or skips all nodes).
|
|
813
|
+
// Scope parents can be far wider than the user anticipates, so we cascade
|
|
814
|
+
// a rightward shift to all downstream nodes that fall inside the expanded box.
|
|
815
|
+
resolvePostLayoutOverlaps(diagramNodes);
|
|
769
816
|
// Compute external port positions
|
|
770
817
|
for (const node of diagramNodes.values()) {
|
|
771
818
|
computePortPositions(node);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "0.13.
|
|
1
|
+
export declare const VERSION = "0.13.2";
|
|
2
2
|
//# sourceMappingURL=generated-version.d.ts.map
|
package/package.json
CHANGED