@synergenius/flow-weaver 0.30.0 → 0.30.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 +18 -6
- package/dist/annotation-generator.js +11 -1
- package/dist/cli/commands/describe.js +1 -1
- package/dist/cli/commands/diagram.js +3 -0
- package/dist/cli/commands/diff.js +2 -2
- package/dist/cli/commands/run.js +2 -2
- package/dist/cli/commands/serve.js +11 -0
- package/dist/cli/commands/validate.js +1 -1
- package/dist/cli/flow-weaver.mjs +126 -234
- package/dist/cli/index.js +0 -11
- package/dist/doc-metadata/extractors/cli-commands.js +0 -10
- package/dist/generated-version.d.ts +1 -1
- package/dist/generated-version.js +1 -1
- package/dist/jsdoc-parser.js +15 -12
- package/docs/reference/cli-reference.md +1 -25
- package/package.json +1 -1
- package/dist/cli/commands/changelog.d.ts +0 -13
- package/dist/cli/commands/changelog.js +0 -135
package/README.md
CHANGED
|
@@ -18,15 +18,27 @@ Flow Weaver is a TypeScript workflow compiler. Define workflows with JSDoc annot
|
|
|
18
18
|
|
|
19
19
|
Build AI agent workflows, data pipelines, or automation scripts through natural language using MCP tools in Claude Code, Cursor, Windsurf, VS Code, JetBrains, Codex, or any MCP-compatible editor. Or write them by hand with annotations the same way you write JSDoc today.
|
|
20
20
|
|
|
21
|
-
##
|
|
21
|
+
## About me & my vision
|
|
22
|
+
|
|
23
|
+
Hey, I am [Ricardo Morais](https://linkedin.com/in/moraispgsi), the project's founder and owner.
|
|
24
|
+
|
|
25
|
+
I have always wondered why Visual Programming never took off. After understanding why I tried to address most of the concerns from the development community:
|
|
26
|
+
- No lock-in: code is compiled and yours, not dependent on this library. You can remove the annotation after compiling and the file is standalone.
|
|
27
|
+
- The code is the source of truth, visual part runs on top, this allows you to create your workflows visually in the Studio, at the end of the day it is just plain Typescript code that you or any LLM can understand and iterate.
|
|
28
|
+
- It being just code opens a lot of doors for you, like using Git for version control, doing all sort of stuff you already do with code like testing, linting, automating, everything.
|
|
29
|
+
- In the era of LLMs and agents, being able to have that control is crucial, it is not a black box, you can see everything and so can your assistant.
|
|
22
30
|
|
|
23
|
-
|
|
31
|
+
As of now this is a solo project and I am building it in the open. There is a lot to do and rough edges to smooth out. If you run into issues or have questions, the [Discord](https://discord.gg/6Byh3ur2bk) is the best place to reach out. Every issue and question gets a response. I genuinely want to hear from you.
|
|
32
|
+
|
|
33
|
+
If this resonates with what you have been looking for, give it a try and let me know how it goes. Stars, feedback, and honest criticism all help equally.
|
|
34
|
+
|
|
35
|
+
## Project Status
|
|
24
36
|
|
|
25
|
-
|
|
37
|
+
Flow Weaver is in **beta**. The compiler, validator, CLI, and MCP tools are stable and thoroughly tested. The test suite covers thousands of cases across parsing, compilation, validation, diffing, and deployment. CI runs on every commit.
|
|
26
38
|
|
|
27
39
|
**Flow Weaver Studio**, the browser-based visual IDE, is the next major milestone and is being actively built. Core editing (canvas, terminal, diagnostics) is live today. The visual debugger, AI chat assistant, version history, and deployment dashboard are in progress. You can follow development on Discord or in the [GitHub releases](https://github.com/synergenius-fw/flow-weaver/releases).
|
|
28
40
|
|
|
29
|
-
Breaking changes may occur between minor versions during
|
|
41
|
+
Breaking changes may still occur between minor versions during beta. Pin your version in `package.json` if stability matters for your project.
|
|
30
42
|
|
|
31
43
|
## Capabilities
|
|
32
44
|
|
|
@@ -224,11 +236,11 @@ export async function supportAgent(
|
|
|
224
236
|
|
|
225
237
|
Run `fw --help` or `fw <command> --help` for full options.
|
|
226
238
|
|
|
227
|
-
## Flow Weaver Studio (
|
|
239
|
+
## Flow Weaver Studio (Beta)
|
|
228
240
|
|
|
229
241
|
A browser-based visual IDE for building workflows. Canvas editor, integrated terminal, real-time diagnostics, and the full CLI available in the cloud.
|
|
230
242
|
|
|
231
|
-
Studio is in
|
|
243
|
+
Studio is in beta. Core editing is live. The visual debugger, AI chat assistant, version history, and deployment dashboard are being actively developed and will ship incrementally. The cloud platform is not yet production-ready, and paid plans are not available yet. Use it to explore and experiment, but expect rough edges.
|
|
232
244
|
|
|
233
245
|
[Open Studio](https://flowweaver.ai/studio) · [Learn more](https://flowweaver.ai/features)
|
|
234
246
|
|
|
@@ -627,7 +627,17 @@ export function generateNodeInstanceTag(instance) {
|
|
|
627
627
|
if (instance.config?.x !== undefined && instance.config?.y !== undefined) {
|
|
628
628
|
positionAttr = ` [position: ${Math.round(instance.config.x)} ${Math.round(instance.config.y)}]`;
|
|
629
629
|
}
|
|
630
|
-
|
|
630
|
+
// Generate [job: "name"] attribute if present (CI/CD job group)
|
|
631
|
+
let jobAttr = '';
|
|
632
|
+
if (instance.job) {
|
|
633
|
+
jobAttr = ` [job: "${instance.job}"]`;
|
|
634
|
+
}
|
|
635
|
+
// Generate [environment: "name"] attribute if present (CI/CD environment)
|
|
636
|
+
let environmentAttr = '';
|
|
637
|
+
if (instance.environment) {
|
|
638
|
+
environmentAttr = ` [environment: "${instance.environment}"]`;
|
|
639
|
+
}
|
|
640
|
+
return ` * @node ${instance.id} ${instance.nodeType}${parent}${labelAttr}${portOrderAttr}${portLabelAttr}${exprAttr}${pullExecutionAttr}${minimizedAttr}${colorAttr}${iconAttr}${tagsAttr}${suppressAttr}${sizeAttr}${positionAttr}${jobAttr}${environmentAttr}`;
|
|
631
641
|
}
|
|
632
642
|
/**
|
|
633
643
|
* Generate a TypeScript function signature from a node type definition.
|
|
@@ -349,7 +349,7 @@ export async function describeCommand(input, options = {}) {
|
|
|
349
349
|
}
|
|
350
350
|
try {
|
|
351
351
|
// Parse the workflow
|
|
352
|
-
const parseResult = await parseWorkflow(filePath, { workflowName });
|
|
352
|
+
const parseResult = await parseWorkflow(filePath, { workflowName, projectDir: path.dirname(filePath) });
|
|
353
353
|
if (parseResult.errors.length > 0) {
|
|
354
354
|
throw new Error(`Parse errors:\n${parseResult.errors.map((err) => ` ${err}`).join('\n')}`);
|
|
355
355
|
}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import * as fs from 'fs';
|
|
6
6
|
import * as path from 'path';
|
|
7
7
|
import { fileToSVG, fileToHTML, fileToASCII } from '../../diagram/index.js';
|
|
8
|
+
import { parser } from '../../parser.js';
|
|
8
9
|
import { logger } from '../utils/logger.js';
|
|
9
10
|
import { safeWriteFile } from '../utils/safe-write.js';
|
|
10
11
|
const ASCII_FORMATS = new Set(['ascii', 'ascii-compact', 'text']);
|
|
@@ -14,6 +15,8 @@ export async function diagramCommand(input, options = {}) {
|
|
|
14
15
|
if (!fs.existsSync(filePath)) {
|
|
15
16
|
throw new Error(`File not found: ${filePath}`);
|
|
16
17
|
}
|
|
18
|
+
// Load marketplace pack tag handlers before parsing
|
|
19
|
+
await parser.loadPackHandlers(path.dirname(filePath));
|
|
17
20
|
let result;
|
|
18
21
|
if (ASCII_FORMATS.has(format)) {
|
|
19
22
|
result = fileToASCII(filePath, { ...diagramOptions, format });
|
|
@@ -21,8 +21,8 @@ export async function diffCommand(file1, file2, options = {}) {
|
|
|
21
21
|
try {
|
|
22
22
|
// Parse both workflows
|
|
23
23
|
const [result1, result2] = await Promise.all([
|
|
24
|
-
parseWorkflow(filePath1, { workflowName }),
|
|
25
|
-
parseWorkflow(filePath2, { workflowName }),
|
|
24
|
+
parseWorkflow(filePath1, { workflowName, projectDir: path.dirname(filePath1) }),
|
|
25
|
+
parseWorkflow(filePath2, { workflowName, projectDir: path.dirname(filePath2) }),
|
|
26
26
|
]);
|
|
27
27
|
if (result1.errors.length > 0) {
|
|
28
28
|
throw new Error(`Parse errors in ${file1}:\n${result1.errors.map((err) => ` ${err}`).join('\n')}`);
|
package/dist/cli/commands/run.js
CHANGED
|
@@ -184,7 +184,7 @@ async function runCommandInner(input, options) {
|
|
|
184
184
|
let executionOrder = resumeExecutionOrder;
|
|
185
185
|
if (!executionOrder) {
|
|
186
186
|
const source = fs.readFileSync(filePath, 'utf8');
|
|
187
|
-
const parsed = await parseWorkflow(source, { workflowName: options.workflow });
|
|
187
|
+
const parsed = await parseWorkflow(source, { workflowName: options.workflow, projectDir: path.dirname(filePath) });
|
|
188
188
|
if (parsed.errors.length === 0) {
|
|
189
189
|
executionOrder = getTopologicalOrder(parsed.ast);
|
|
190
190
|
}
|
|
@@ -427,7 +427,7 @@ export async function validateMockConfig(mocks, filePath, workflowName) {
|
|
|
427
427
|
}
|
|
428
428
|
// Quick-parse the workflow to check which built-in node types are used
|
|
429
429
|
try {
|
|
430
|
-
const result = await parseWorkflow(filePath, { workflowName });
|
|
430
|
+
const result = await parseWorkflow(filePath, { workflowName, projectDir: path.dirname(filePath) });
|
|
431
431
|
if (result.errors.length > 0 || !result.ast?.instances)
|
|
432
432
|
return;
|
|
433
433
|
const usedNodeTypes = new Set(result.ast.instances.map((i) => i.nodeType));
|
|
@@ -30,6 +30,17 @@ import { logger } from '../utils/logger.js';
|
|
|
30
30
|
* ```
|
|
31
31
|
*/
|
|
32
32
|
export async function serveCommand(dir, options) {
|
|
33
|
+
// Check fastify is installed before proceeding
|
|
34
|
+
try {
|
|
35
|
+
await import('fastify');
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
logger.error('The serve command requires fastify. Install it with:');
|
|
39
|
+
logger.newline();
|
|
40
|
+
logger.log(' npm install fastify');
|
|
41
|
+
logger.newline();
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
33
44
|
const workflowDir = path.resolve(dir || '.');
|
|
34
45
|
// Validate directory exists
|
|
35
46
|
if (!fs.existsSync(workflowDir)) {
|
|
@@ -62,7 +62,7 @@ export async function validateCommand(input, options = {}) {
|
|
|
62
62
|
}
|
|
63
63
|
try {
|
|
64
64
|
// Parse the workflow
|
|
65
|
-
const parseResult = await parseWorkflow(file, { workflowName, projectDir:
|
|
65
|
+
const parseResult = await parseWorkflow(file, { workflowName, projectDir: path.dirname(path.resolve(file)) });
|
|
66
66
|
if (parseResult.warnings.length > 0) {
|
|
67
67
|
if (!json && !quiet) {
|
|
68
68
|
logger.warn(`Parse warnings in ${fileName}:`);
|