@synergenius/flow-weaver 0.2.0
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/LICENSE +122 -0
- package/README.md +315 -0
- package/dist/annotation-generator.d.ts +45 -0
- package/dist/annotation-generator.js +557 -0
- package/dist/api/builder.d.ts +223 -0
- package/dist/api/builder.js +345 -0
- package/dist/api/compile.d.ts +92 -0
- package/dist/api/compile.js +149 -0
- package/dist/api/extract-types.d.ts +29 -0
- package/dist/api/extract-types.js +57 -0
- package/dist/api/generate-in-place.d.ts +73 -0
- package/dist/api/generate-in-place.js +1353 -0
- package/dist/api/generate.d.ts +83 -0
- package/dist/api/generate.js +510 -0
- package/dist/api/helpers.d.ts +248 -0
- package/dist/api/helpers.js +285 -0
- package/dist/api/index.d.ts +46 -0
- package/dist/api/index.js +45 -0
- package/dist/api/inline-runtime.d.ts +27 -0
- package/dist/api/inline-runtime.js +551 -0
- package/dist/api/manipulation/connections.d.ts +79 -0
- package/dist/api/manipulation/connections.js +151 -0
- package/dist/api/manipulation/index.d.ts +34 -0
- package/dist/api/manipulation/index.js +41 -0
- package/dist/api/manipulation/node-types.d.ts +123 -0
- package/dist/api/manipulation/node-types.js +200 -0
- package/dist/api/manipulation/nodes.d.ts +144 -0
- package/dist/api/manipulation/nodes.js +333 -0
- package/dist/api/manipulation/ports.d.ts +59 -0
- package/dist/api/manipulation/ports.js +228 -0
- package/dist/api/manipulation/scopes.d.ts +52 -0
- package/dist/api/manipulation/scopes.js +156 -0
- package/dist/api/manipulation/validation.d.ts +6 -0
- package/dist/api/manipulation/validation.js +6 -0
- package/dist/api/manipulation/workflow.d.ts +81 -0
- package/dist/api/manipulation/workflow.js +116 -0
- package/dist/api/manipulation.d.ts +8 -0
- package/dist/api/manipulation.js +8 -0
- package/dist/api/parse.d.ts +48 -0
- package/dist/api/parse.js +110 -0
- package/dist/api/patterns.d.ts +112 -0
- package/dist/api/patterns.js +306 -0
- package/dist/api/query.d.ts +429 -0
- package/dist/api/query.js +816 -0
- package/dist/api/templates.d.ts +98 -0
- package/dist/api/templates.js +117 -0
- package/dist/api/transform.d.ts +31 -0
- package/dist/api/transform.js +40 -0
- package/dist/api/validate.d.ts +25 -0
- package/dist/api/validate.js +39 -0
- package/dist/api/workflow-file-operations.d.ts +29 -0
- package/dist/api/workflow-file-operations.js +180 -0
- package/dist/ast/builder.d.ts +210 -0
- package/dist/ast/builder.js +395 -0
- package/dist/ast/index.d.ts +5 -0
- package/dist/ast/index.js +5 -0
- package/dist/ast/serialization-node.d.ts +6 -0
- package/dist/ast/serialization-node.js +30 -0
- package/dist/ast/serialization.d.ts +43 -0
- package/dist/ast/serialization.js +134 -0
- package/dist/ast/types.d.ts +852 -0
- package/dist/ast/types.js +2 -0
- package/dist/ast/workflow-utils.d.ts +54 -0
- package/dist/ast/workflow-utils.js +114 -0
- package/dist/body-generator.d.ts +31 -0
- package/dist/body-generator.js +35 -0
- package/dist/built-in-nodes/delay.d.ts +11 -0
- package/dist/built-in-nodes/delay.js +29 -0
- package/dist/built-in-nodes/index.d.ts +5 -0
- package/dist/built-in-nodes/index.js +4 -0
- package/dist/built-in-nodes/invoke-workflow.d.ts +13 -0
- package/dist/built-in-nodes/invoke-workflow.js +25 -0
- package/dist/built-in-nodes/mock-types.d.ts +18 -0
- package/dist/built-in-nodes/mock-types.js +12 -0
- package/dist/built-in-nodes/wait-for-event.d.ts +13 -0
- package/dist/built-in-nodes/wait-for-event.js +25 -0
- package/dist/chevrotain-parser/connect-parser.d.ts +24 -0
- package/dist/chevrotain-parser/connect-parser.js +98 -0
- package/dist/chevrotain-parser/grammar-diagrams.d.ts +29 -0
- package/dist/chevrotain-parser/grammar-diagrams.js +264 -0
- package/dist/chevrotain-parser/index.d.ts +25 -0
- package/dist/chevrotain-parser/index.js +27 -0
- package/dist/chevrotain-parser/map-parser.d.ts +33 -0
- package/dist/chevrotain-parser/map-parser.js +130 -0
- package/dist/chevrotain-parser/node-parser.d.ts +36 -0
- package/dist/chevrotain-parser/node-parser.js +466 -0
- package/dist/chevrotain-parser/path-parser.d.ts +28 -0
- package/dist/chevrotain-parser/path-parser.js +118 -0
- package/dist/chevrotain-parser/port-parser.d.ts +36 -0
- package/dist/chevrotain-parser/port-parser.js +442 -0
- package/dist/chevrotain-parser/position-parser.d.ts +20 -0
- package/dist/chevrotain-parser/position-parser.js +83 -0
- package/dist/chevrotain-parser/scope-parser.d.ts +19 -0
- package/dist/chevrotain-parser/scope-parser.js +104 -0
- package/dist/chevrotain-parser/tokens.d.ts +78 -0
- package/dist/chevrotain-parser/tokens.js +384 -0
- package/dist/chevrotain-parser/trigger-cancel-parser.d.ts +50 -0
- package/dist/chevrotain-parser/trigger-cancel-parser.js +282 -0
- package/dist/cli/commands/changelog.d.ts +13 -0
- package/dist/cli/commands/changelog.js +135 -0
- package/dist/cli/commands/compile.d.ts +64 -0
- package/dist/cli/commands/compile.js +278 -0
- package/dist/cli/commands/create.d.ts +33 -0
- package/dist/cli/commands/create.js +147 -0
- package/dist/cli/commands/describe.d.ts +68 -0
- package/dist/cli/commands/describe.js +377 -0
- package/dist/cli/commands/dev.d.ts +32 -0
- package/dist/cli/commands/dev.js +384 -0
- package/dist/cli/commands/diagram.d.ts +13 -0
- package/dist/cli/commands/diagram.js +33 -0
- package/dist/cli/commands/diff.d.ts +11 -0
- package/dist/cli/commands/diff.js +59 -0
- package/dist/cli/commands/doctor.d.ts +57 -0
- package/dist/cli/commands/doctor.js +719 -0
- package/dist/cli/commands/export.d.ts +57 -0
- package/dist/cli/commands/export.js +163 -0
- package/dist/cli/commands/grammar.d.ts +9 -0
- package/dist/cli/commands/grammar.js +39 -0
- package/dist/cli/commands/init.d.ts +59 -0
- package/dist/cli/commands/init.js +435 -0
- package/dist/cli/commands/listen.d.ts +16 -0
- package/dist/cli/commands/listen.js +39 -0
- package/dist/cli/commands/market.d.ts +52 -0
- package/dist/cli/commands/market.js +436 -0
- package/dist/cli/commands/migrate.d.ts +13 -0
- package/dist/cli/commands/migrate.js +89 -0
- package/dist/cli/commands/openapi.d.ts +37 -0
- package/dist/cli/commands/openapi.js +67 -0
- package/dist/cli/commands/pattern.d.ts +34 -0
- package/dist/cli/commands/pattern.js +185 -0
- package/dist/cli/commands/plugin.d.ts +16 -0
- package/dist/cli/commands/plugin.js +176 -0
- package/dist/cli/commands/run.d.ts +49 -0
- package/dist/cli/commands/run.js +191 -0
- package/dist/cli/commands/serve.d.ts +45 -0
- package/dist/cli/commands/serve.js +81 -0
- package/dist/cli/commands/templates.d.ts +8 -0
- package/dist/cli/commands/templates.js +54 -0
- package/dist/cli/commands/ui.d.ts +16 -0
- package/dist/cli/commands/ui.js +130 -0
- package/dist/cli/commands/validate.d.ts +12 -0
- package/dist/cli/commands/validate.js +247 -0
- package/dist/cli/commands/watch.d.ts +9 -0
- package/dist/cli/commands/watch.js +70 -0
- package/dist/cli/flow-weaver.mjs +92924 -0
- package/dist/cli/index.d.ts +9 -0
- package/dist/cli/index.js +742 -0
- package/dist/cli/templates/ai/mock-provider.d.ts +7 -0
- package/dist/cli/templates/ai/mock-provider.js +64 -0
- package/dist/cli/templates/ai/types.d.ts +47 -0
- package/dist/cli/templates/ai/types.js +5 -0
- package/dist/cli/templates/approvals/index.d.ts +15 -0
- package/dist/cli/templates/approvals/index.js +241 -0
- package/dist/cli/templates/index.d.ts +102 -0
- package/dist/cli/templates/index.js +101 -0
- package/dist/cli/templates/nodes/agent-router.d.ts +3 -0
- package/dist/cli/templates/nodes/agent-router.js +114 -0
- package/dist/cli/templates/nodes/aggregator.d.ts +7 -0
- package/dist/cli/templates/nodes/aggregator.js +63 -0
- package/dist/cli/templates/nodes/conversation-memory.d.ts +3 -0
- package/dist/cli/templates/nodes/conversation-memory.js +85 -0
- package/dist/cli/templates/nodes/http.d.ts +7 -0
- package/dist/cli/templates/nodes/http.js +80 -0
- package/dist/cli/templates/nodes/human-approval.d.ts +3 -0
- package/dist/cli/templates/nodes/human-approval.js +110 -0
- package/dist/cli/templates/nodes/json-extractor.d.ts +3 -0
- package/dist/cli/templates/nodes/json-extractor.js +119 -0
- package/dist/cli/templates/nodes/llm-call.d.ts +3 -0
- package/dist/cli/templates/nodes/llm-call.js +106 -0
- package/dist/cli/templates/nodes/prompt-template.d.ts +3 -0
- package/dist/cli/templates/nodes/prompt-template.js +52 -0
- package/dist/cli/templates/nodes/rag-retriever.d.ts +3 -0
- package/dist/cli/templates/nodes/rag-retriever.js +128 -0
- package/dist/cli/templates/nodes/tool-executor.d.ts +3 -0
- package/dist/cli/templates/nodes/tool-executor.js +108 -0
- package/dist/cli/templates/nodes/transformer.d.ts +7 -0
- package/dist/cli/templates/nodes/transformer.js +68 -0
- package/dist/cli/templates/nodes/validator.d.ts +7 -0
- package/dist/cli/templates/nodes/validator.js +62 -0
- package/dist/cli/templates/providers/index.d.ts +14 -0
- package/dist/cli/templates/providers/index.js +239 -0
- package/dist/cli/templates/shared/approval-types.d.ts +9 -0
- package/dist/cli/templates/shared/approval-types.js +31 -0
- package/dist/cli/templates/shared/llm-types.d.ts +15 -0
- package/dist/cli/templates/shared/llm-types.js +104 -0
- package/dist/cli/templates/workflows/aggregator.d.ts +7 -0
- package/dist/cli/templates/workflows/aggregator.js +104 -0
- package/dist/cli/templates/workflows/ai-agent-durable.d.ts +8 -0
- package/dist/cli/templates/workflows/ai-agent-durable.js +338 -0
- package/dist/cli/templates/workflows/ai-agent.d.ts +31 -0
- package/dist/cli/templates/workflows/ai-agent.js +326 -0
- package/dist/cli/templates/workflows/ai-chat.d.ts +7 -0
- package/dist/cli/templates/workflows/ai-chat.js +169 -0
- package/dist/cli/templates/workflows/ai-pipeline-durable.d.ts +8 -0
- package/dist/cli/templates/workflows/ai-pipeline-durable.js +330 -0
- package/dist/cli/templates/workflows/ai-rag.d.ts +7 -0
- package/dist/cli/templates/workflows/ai-rag.js +186 -0
- package/dist/cli/templates/workflows/ai-react.d.ts +7 -0
- package/dist/cli/templates/workflows/ai-react.js +294 -0
- package/dist/cli/templates/workflows/conditional.d.ts +12 -0
- package/dist/cli/templates/workflows/conditional.js +142 -0
- package/dist/cli/templates/workflows/error-handler.d.ts +7 -0
- package/dist/cli/templates/workflows/error-handler.js +147 -0
- package/dist/cli/templates/workflows/foreach.d.ts +7 -0
- package/dist/cli/templates/workflows/foreach.js +143 -0
- package/dist/cli/templates/workflows/sequential.d.ts +7 -0
- package/dist/cli/templates/workflows/sequential.js +198 -0
- package/dist/cli/templates/workflows/webhook.d.ts +7 -0
- package/dist/cli/templates/workflows/webhook.js +161 -0
- package/dist/cli/utils/logger.d.ts +15 -0
- package/dist/cli/utils/logger.js +46 -0
- package/dist/constants.d.ts +100 -0
- package/dist/constants.js +125 -0
- package/dist/defaults.d.ts +3 -0
- package/dist/defaults.js +3 -0
- package/dist/deployment/config/defaults.d.ts +29 -0
- package/dist/deployment/config/defaults.js +98 -0
- package/dist/deployment/config/loader.d.ts +24 -0
- package/dist/deployment/config/loader.js +236 -0
- package/dist/deployment/config/types.d.ts +117 -0
- package/dist/deployment/config/types.js +5 -0
- package/dist/deployment/core/adapters.d.ts +90 -0
- package/dist/deployment/core/adapters.js +251 -0
- package/dist/deployment/core/executor.d.ts +62 -0
- package/dist/deployment/core/executor.js +197 -0
- package/dist/deployment/core/formatters.d.ts +57 -0
- package/dist/deployment/core/formatters.js +170 -0
- package/dist/deployment/index.d.ts +31 -0
- package/dist/deployment/index.js +48 -0
- package/dist/deployment/openapi/generator.d.ts +146 -0
- package/dist/deployment/openapi/generator.js +347 -0
- package/dist/deployment/openapi/schema-converter.d.ts +49 -0
- package/dist/deployment/openapi/schema-converter.js +192 -0
- package/dist/deployment/targets/base.d.ts +316 -0
- package/dist/deployment/targets/base.js +823 -0
- package/dist/deployment/targets/cloudflare.d.ts +23 -0
- package/dist/deployment/targets/cloudflare.js +1125 -0
- package/dist/deployment/targets/inngest.d.ts +38 -0
- package/dist/deployment/targets/inngest.js +926 -0
- package/dist/deployment/targets/lambda.d.ts +23 -0
- package/dist/deployment/targets/lambda.js +1289 -0
- package/dist/deployment/targets/vercel.d.ts +23 -0
- package/dist/deployment/targets/vercel.js +886 -0
- package/dist/deployment/types.d.ts +183 -0
- package/dist/deployment/types.js +8 -0
- package/dist/diagram/geometry.d.ts +26 -0
- package/dist/diagram/geometry.js +850 -0
- package/dist/diagram/index.d.ts +16 -0
- package/dist/diagram/index.js +42 -0
- package/dist/diagram/layout.d.ts +11 -0
- package/dist/diagram/layout.js +143 -0
- package/dist/diagram/orthogonal-router.d.ts +79 -0
- package/dist/diagram/orthogonal-router.js +568 -0
- package/dist/diagram/renderer.d.ts +3 -0
- package/dist/diagram/renderer.js +207 -0
- package/dist/diagram/theme.d.ts +20 -0
- package/dist/diagram/theme.js +189 -0
- package/dist/diagram/types.d.ts +70 -0
- package/dist/diagram/types.js +2 -0
- package/dist/diff/WorkflowDiffer.d.ts +13 -0
- package/dist/diff/WorkflowDiffer.js +429 -0
- package/dist/diff/formatDiff.d.ts +10 -0
- package/dist/diff/formatDiff.js +220 -0
- package/dist/diff/impact.d.ts +29 -0
- package/dist/diff/impact.js +119 -0
- package/dist/diff/index.d.ts +10 -0
- package/dist/diff/index.js +9 -0
- package/dist/diff/types.d.ts +138 -0
- package/dist/diff/types.js +35 -0
- package/dist/doc-metadata/extractors/annotations.d.ts +56 -0
- package/dist/doc-metadata/extractors/annotations.js +337 -0
- package/dist/doc-metadata/extractors/cli-commands.d.ts +17 -0
- package/dist/doc-metadata/extractors/cli-commands.js +355 -0
- package/dist/doc-metadata/extractors/mcp-tools.d.ts +16 -0
- package/dist/doc-metadata/extractors/mcp-tools.js +689 -0
- package/dist/doc-metadata/extractors/plugin-api.d.ts +19 -0
- package/dist/doc-metadata/extractors/plugin-api.js +279 -0
- package/dist/doc-metadata/index.d.ts +5 -0
- package/dist/doc-metadata/index.js +4 -0
- package/dist/doc-metadata/types.d.ts +120 -0
- package/dist/doc-metadata/types.js +5 -0
- package/dist/editor-completions/annotationValues.d.ts +12 -0
- package/dist/editor-completions/annotationValues.js +138 -0
- package/dist/editor-completions/contextParser.d.ts +40 -0
- package/dist/editor-completions/contextParser.js +410 -0
- package/dist/editor-completions/dataTypes.d.ts +16 -0
- package/dist/editor-completions/dataTypes.js +95 -0
- package/dist/editor-completions/goToDefinition.d.ts +27 -0
- package/dist/editor-completions/goToDefinition.js +112 -0
- package/dist/editor-completions/index.d.ts +39 -0
- package/dist/editor-completions/index.js +181 -0
- package/dist/editor-completions/jsDocAnnotations.d.ts +29 -0
- package/dist/editor-completions/jsDocAnnotations.js +357 -0
- package/dist/editor-completions/modifierCompletions.d.ts +17 -0
- package/dist/editor-completions/modifierCompletions.js +197 -0
- package/dist/editor-completions/types.d.ts +119 -0
- package/dist/editor-completions/types.js +8 -0
- package/dist/export/index.d.ts +68 -0
- package/dist/export/index.js +1074 -0
- package/dist/export/templates.d.ts +24 -0
- package/dist/export/templates.js +186 -0
- package/dist/friendly-errors.d.ts +35 -0
- package/dist/friendly-errors.js +375 -0
- package/dist/function-like.d.ts +38 -0
- package/dist/function-like.js +83 -0
- package/dist/generated-branding.d.ts +16 -0
- package/dist/generated-branding.js +22 -0
- package/dist/generator/async-detection.d.ts +27 -0
- package/dist/generator/async-detection.js +56 -0
- package/dist/generator/code-utils.d.ts +76 -0
- package/dist/generator/code-utils.js +410 -0
- package/dist/generator/control-flow.d.ts +54 -0
- package/dist/generator/control-flow.js +284 -0
- package/dist/generator/inngest.d.ts +53 -0
- package/dist/generator/inngest.js +1126 -0
- package/dist/generator/scope-function-generator.d.ts +78 -0
- package/dist/generator/scope-function-generator.js +360 -0
- package/dist/generator/unified.d.ts +42 -0
- package/dist/generator/unified.js +1504 -0
- package/dist/generator.d.ts +54 -0
- package/dist/generator.js +100 -0
- package/dist/index.d.ts +85 -0
- package/dist/index.js +89 -0
- package/dist/jsdoc-parser.d.ts +308 -0
- package/dist/jsdoc-parser.js +923 -0
- package/dist/jsdoc-port-sync/constants.d.ts +41 -0
- package/dist/jsdoc-port-sync/constants.js +103 -0
- package/dist/jsdoc-port-sync/diff.d.ts +76 -0
- package/dist/jsdoc-port-sync/diff.js +319 -0
- package/dist/jsdoc-port-sync/index.d.ts +42 -0
- package/dist/jsdoc-port-sync/index.js +45 -0
- package/dist/jsdoc-port-sync/port-parser.d.ts +68 -0
- package/dist/jsdoc-port-sync/port-parser.js +579 -0
- package/dist/jsdoc-port-sync/rename.d.ts +21 -0
- package/dist/jsdoc-port-sync/rename.js +256 -0
- package/dist/jsdoc-port-sync/signature-parser.d.ts +104 -0
- package/dist/jsdoc-port-sync/signature-parser.js +559 -0
- package/dist/jsdoc-port-sync/sync.d.ts +36 -0
- package/dist/jsdoc-port-sync/sync.js +644 -0
- package/dist/jsdoc-port-sync.d.ts +10 -0
- package/dist/jsdoc-port-sync.js +10 -0
- package/dist/marketplace/index.d.ts +11 -0
- package/dist/marketplace/index.js +10 -0
- package/dist/marketplace/manifest.d.ts +32 -0
- package/dist/marketplace/manifest.js +176 -0
- package/dist/marketplace/registry.d.ts +30 -0
- package/dist/marketplace/registry.js +100 -0
- package/dist/marketplace/types.d.ts +154 -0
- package/dist/marketplace/types.js +9 -0
- package/dist/marketplace/validator.d.ts +13 -0
- package/dist/marketplace/validator.js +131 -0
- package/dist/mcp/auto-registration.d.ts +3 -0
- package/dist/mcp/auto-registration.js +62 -0
- package/dist/mcp/editor-connection.d.ts +50 -0
- package/dist/mcp/editor-connection.js +125 -0
- package/dist/mcp/event-buffer.d.ts +62 -0
- package/dist/mcp/event-buffer.js +150 -0
- package/dist/mcp/index.d.ts +12 -0
- package/dist/mcp/index.js +11 -0
- package/dist/mcp/resources.d.ts +14 -0
- package/dist/mcp/resources.js +55 -0
- package/dist/mcp/response-utils.d.ts +63 -0
- package/dist/mcp/response-utils.js +89 -0
- package/dist/mcp/server.d.ts +4 -0
- package/dist/mcp/server.js +99 -0
- package/dist/mcp/tools-diagram.d.ts +8 -0
- package/dist/mcp/tools-diagram.js +53 -0
- package/dist/mcp/tools-editor.d.ts +5 -0
- package/dist/mcp/tools-editor.js +190 -0
- package/dist/mcp/tools-export.d.ts +9 -0
- package/dist/mcp/tools-export.js +180 -0
- package/dist/mcp/tools-marketplace.d.ts +9 -0
- package/dist/mcp/tools-marketplace.js +132 -0
- package/dist/mcp/tools-pattern.d.ts +3 -0
- package/dist/mcp/tools-pattern.js +783 -0
- package/dist/mcp/tools-query.d.ts +3 -0
- package/dist/mcp/tools-query.js +364 -0
- package/dist/mcp/tools-template.d.ts +10 -0
- package/dist/mcp/tools-template.js +119 -0
- package/dist/mcp/types.d.ts +70 -0
- package/dist/mcp/types.js +8 -0
- package/dist/mcp/workflow-executor.d.ts +47 -0
- package/dist/mcp/workflow-executor.js +133 -0
- package/dist/migration/registry.d.ts +30 -0
- package/dist/migration/registry.js +29 -0
- package/dist/node-types-generator.d.ts +49 -0
- package/dist/node-types-generator.js +139 -0
- package/dist/npm-packages.d.ts +56 -0
- package/dist/npm-packages.js +255 -0
- package/dist/parser.d.ts +204 -0
- package/dist/parser.js +2100 -0
- package/dist/plugin/PluginPanel.d.ts +12 -0
- package/dist/plugin/PluginPanel.js +5 -0
- package/dist/plugin/index.d.ts +13 -0
- package/dist/plugin/index.js +14 -0
- package/dist/plugin/types.d.ts +75 -0
- package/dist/plugin/types.js +8 -0
- package/dist/resolve-package-types.d.ts +17 -0
- package/dist/resolve-package-types.js +123 -0
- package/dist/runtime/CancellationError.d.ts +11 -0
- package/dist/runtime/CancellationError.js +20 -0
- package/dist/runtime/ExecutionContext.d.ts +146 -0
- package/dist/runtime/ExecutionContext.js +235 -0
- package/dist/runtime/builtin-functions.d.ts +8 -0
- package/dist/runtime/builtin-functions.js +549 -0
- package/dist/runtime/events.d.ts +50 -0
- package/dist/runtime/events.js +2 -0
- package/dist/runtime/function-registry.d.ts +59 -0
- package/dist/runtime/function-registry.js +66 -0
- package/dist/runtime/index.d.ts +7 -0
- package/dist/runtime/index.js +7 -0
- package/dist/runtime/parameter-resolver.d.ts +62 -0
- package/dist/runtime/parameter-resolver.js +113 -0
- package/dist/server/index.d.ts +7 -0
- package/dist/server/index.js +6 -0
- package/dist/server/types.d.ts +93 -0
- package/dist/server/types.js +5 -0
- package/dist/server/webhook-server.d.ts +50 -0
- package/dist/server/webhook-server.js +269 -0
- package/dist/server/workflow-registry.d.ts +61 -0
- package/dist/server/workflow-registry.js +202 -0
- package/dist/shared-project.d.ts +9 -0
- package/dist/shared-project.js +28 -0
- package/dist/sugar-optimizer.d.ts +40 -0
- package/dist/sugar-optimizer.js +387 -0
- package/dist/testing/assertions.d.ts +51 -0
- package/dist/testing/assertions.js +127 -0
- package/dist/testing/index.d.ts +30 -0
- package/dist/testing/index.js +24 -0
- package/dist/testing/mock-approval.d.ts +81 -0
- package/dist/testing/mock-approval.js +98 -0
- package/dist/testing/mock-llm.d.ts +124 -0
- package/dist/testing/mock-llm.js +119 -0
- package/dist/testing/recorder.d.ts +72 -0
- package/dist/testing/recorder.js +70 -0
- package/dist/testing/replayer.d.ts +56 -0
- package/dist/testing/replayer.js +143 -0
- package/dist/testing/token-tracker.d.ts +71 -0
- package/dist/testing/token-tracker.js +94 -0
- package/dist/type-checker.d.ts +42 -0
- package/dist/type-checker.js +190 -0
- package/dist/type-mappings.d.ts +29 -0
- package/dist/type-mappings.js +125 -0
- package/dist/types/branded-ports.d.ts +151 -0
- package/dist/types/branded-ports.js +121 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.js +5 -0
- package/dist/types.d.ts +139 -0
- package/dist/types.js +15 -0
- package/dist/utils/error-utils.d.ts +15 -0
- package/dist/utils/error-utils.js +27 -0
- package/dist/utils/lru-cache.d.ts +15 -0
- package/dist/utils/lru-cache.js +40 -0
- package/dist/utils/port-ordering.d.ts +26 -0
- package/dist/utils/port-ordering.js +88 -0
- package/dist/utils/port-tag-utils.d.ts +23 -0
- package/dist/utils/port-tag-utils.js +41 -0
- package/dist/utils/string-distance.d.ts +14 -0
- package/dist/utils/string-distance.js +56 -0
- package/dist/validation/agent-detection.d.ts +33 -0
- package/dist/validation/agent-detection.js +115 -0
- package/dist/validation/agent-rules.d.ts +48 -0
- package/dist/validation/agent-rules.js +262 -0
- package/dist/validator.d.ts +92 -0
- package/dist/validator.js +970 -0
- package/package.json +109 -0
|
@@ -0,0 +1,816 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Query API for read-only workflow inspection
|
|
3
|
+
* All functions are pure and do not modify the workflow
|
|
4
|
+
*/
|
|
5
|
+
import { portReferencesEqual } from './helpers.js';
|
|
6
|
+
import { isPerPortScopedChild } from '../generator/control-flow.js';
|
|
7
|
+
// ============================================================================
|
|
8
|
+
// SCOPE HELPERS
|
|
9
|
+
// ============================================================================
|
|
10
|
+
/**
|
|
11
|
+
* Get connections that belong to the main control flow (exclude scoped connections).
|
|
12
|
+
* Mirrors the filtering logic in control-flow.ts buildControlFlowGraph().
|
|
13
|
+
*/
|
|
14
|
+
function getMainFlowConnections(ast) {
|
|
15
|
+
return ast.connections.filter((conn) => {
|
|
16
|
+
// Skip connections with scope annotation on either end
|
|
17
|
+
if (conn.from.scope || conn.to.scope)
|
|
18
|
+
return false;
|
|
19
|
+
// Skip connections involving per-port scoped children
|
|
20
|
+
const fromInstance = ast.instances.find((i) => i.id === conn.from.node);
|
|
21
|
+
const toInstance = ast.instances.find((i) => i.id === conn.to.node);
|
|
22
|
+
if ((fromInstance && isPerPortScopedChild(fromInstance, ast, ast.nodeTypes)) ||
|
|
23
|
+
(toInstance && isPerPortScopedChild(toInstance, ast, ast.nodeTypes))) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
return true;
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Get instances that belong to the main control flow (exclude per-port scoped children).
|
|
31
|
+
*/
|
|
32
|
+
function getMainFlowInstances(ast) {
|
|
33
|
+
return ast.instances.filter((inst) => !isPerPortScopedChild(inst, ast, ast.nodeTypes));
|
|
34
|
+
}
|
|
35
|
+
// ============================================================================
|
|
36
|
+
// NODE QUERIES
|
|
37
|
+
// ============================================================================
|
|
38
|
+
/**
|
|
39
|
+
* Get a single node instance by ID
|
|
40
|
+
*
|
|
41
|
+
* @param ast - Workflow to query
|
|
42
|
+
* @param nodeId - ID of node to retrieve
|
|
43
|
+
* @returns Node instance or undefined
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```typescript
|
|
47
|
+
* const node = getNode(workflow, 'processor1');
|
|
48
|
+
* if (node) {
|
|
49
|
+
* console.log(`Node type: ${node.nodeType}`);
|
|
50
|
+
* }
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export function getNode(ast, nodeId) {
|
|
54
|
+
return ast.instances.find((n) => n.id === nodeId);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Get all node instances, optionally filtered
|
|
58
|
+
*
|
|
59
|
+
* @param ast - Workflow to query
|
|
60
|
+
* @param filter - Optional filter criteria
|
|
61
|
+
* @returns Array of matching node instances
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```typescript
|
|
65
|
+
* // Get all nodes
|
|
66
|
+
* const allNodes = getNodes(workflow);
|
|
67
|
+
*
|
|
68
|
+
* // Get nodes of specific type
|
|
69
|
+
* const processors = getNodes(workflow, { type: 'processor' });
|
|
70
|
+
*
|
|
71
|
+
* // Get nodes in specific scope
|
|
72
|
+
* const scopedNodes = getNodes(workflow, { scope: 'mainLoop' });
|
|
73
|
+
*
|
|
74
|
+
* // Custom filter
|
|
75
|
+
* const configured = getNodes(workflow, {
|
|
76
|
+
* predicate: (node) => node.config !== undefined
|
|
77
|
+
* });
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export function getNodes(ast, filter) {
|
|
81
|
+
let nodes = [...ast.instances];
|
|
82
|
+
if (!filter) {
|
|
83
|
+
return nodes;
|
|
84
|
+
}
|
|
85
|
+
// Filter by type
|
|
86
|
+
if (filter.type) {
|
|
87
|
+
nodes = nodes.filter((n) => n.nodeType === filter.type);
|
|
88
|
+
}
|
|
89
|
+
// Filter by scope
|
|
90
|
+
if (filter.scope) {
|
|
91
|
+
nodes = nodes.filter((n) => {
|
|
92
|
+
if (!n.parent)
|
|
93
|
+
return false;
|
|
94
|
+
// Match by parent id (simple scope) or full qualified path
|
|
95
|
+
return (n.parent.id === filter.scope ||
|
|
96
|
+
(n.parent.scope && `${n.parent.id}.${n.parent.scope}` === filter.scope));
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
// Apply custom predicate
|
|
100
|
+
if (filter.predicate) {
|
|
101
|
+
nodes = nodes.filter(filter.predicate);
|
|
102
|
+
}
|
|
103
|
+
return nodes;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Get all nodes of a specific type
|
|
107
|
+
*
|
|
108
|
+
* @param ast - Workflow to query
|
|
109
|
+
* @param nodeType - Node type (functionName) to filter by
|
|
110
|
+
* @returns Array of matching node instances
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* ```typescript
|
|
114
|
+
* const processors = getNodesByType(workflow, 'process');
|
|
115
|
+
* console.log(`Found ${processors.length} processor nodes`);
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
export function getNodesByType(ast, nodeType) {
|
|
119
|
+
return ast.instances.filter((n) => n.nodeType === nodeType);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Get all nodes in a specific scope
|
|
123
|
+
*
|
|
124
|
+
* @param ast - Workflow to query
|
|
125
|
+
* @param scopeName - Name of scope
|
|
126
|
+
* @returns Array of node instances in the scope
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* ```typescript
|
|
130
|
+
* const loopNodes = getNodesInScope(workflow, 'mainLoop');
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
133
|
+
export function getNodesInScope(ast, scopeName) {
|
|
134
|
+
return ast.instances.filter((n) => {
|
|
135
|
+
if (!n.parent)
|
|
136
|
+
return false;
|
|
137
|
+
// Match by parent id (simple scope) or full qualified path
|
|
138
|
+
return (n.parent.id === scopeName ||
|
|
139
|
+
(n.parent.scope && `${n.parent.id}.${n.parent.scope}` === scopeName));
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Check if a node exists
|
|
144
|
+
*
|
|
145
|
+
* @param ast - Workflow to query
|
|
146
|
+
* @param nodeId - ID of node to check
|
|
147
|
+
* @returns True if node exists
|
|
148
|
+
*
|
|
149
|
+
* @example
|
|
150
|
+
* ```typescript
|
|
151
|
+
* if (hasNode(workflow, 'processor1')) {
|
|
152
|
+
* console.log('Node exists');
|
|
153
|
+
* }
|
|
154
|
+
* ```
|
|
155
|
+
*/
|
|
156
|
+
export function hasNode(ast, nodeId) {
|
|
157
|
+
return ast.instances.some((n) => n.id === nodeId);
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Find nodes by name pattern (searches in config.label)
|
|
161
|
+
*
|
|
162
|
+
* @param ast - Workflow to query
|
|
163
|
+
* @param pattern - String pattern or regex to match
|
|
164
|
+
* @param caseSensitive - Whether to match case-sensitively (default: false)
|
|
165
|
+
* @returns Array of matching node instances
|
|
166
|
+
*
|
|
167
|
+
* @example
|
|
168
|
+
* ```typescript
|
|
169
|
+
* // Find nodes with 'processor' in label
|
|
170
|
+
* const nodes = findNodesByName(workflow, 'processor');
|
|
171
|
+
*
|
|
172
|
+
* // Case-sensitive search
|
|
173
|
+
* const exact = findNodesByName(workflow, 'Processor', true);
|
|
174
|
+
*
|
|
175
|
+
* // Regex search
|
|
176
|
+
* const regex = findNodesByName(workflow, /^proc-\d+$/);
|
|
177
|
+
* ```
|
|
178
|
+
*/
|
|
179
|
+
export function findNodesByName(ast, pattern, caseSensitive = false) {
|
|
180
|
+
const regex = typeof pattern === 'string' ? new RegExp(pattern, caseSensitive ? '' : 'i') : pattern;
|
|
181
|
+
return ast.instances.filter((node) => {
|
|
182
|
+
// Check node ID
|
|
183
|
+
if (regex.test(node.id)) {
|
|
184
|
+
return true;
|
|
185
|
+
}
|
|
186
|
+
// Check config label if present
|
|
187
|
+
if (node.config?.label && regex.test(node.config.label)) {
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
return false;
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
// ============================================================================
|
|
194
|
+
// CONNECTION QUERIES
|
|
195
|
+
// ============================================================================
|
|
196
|
+
/**
|
|
197
|
+
* Get all connections, optionally filtered by node
|
|
198
|
+
*
|
|
199
|
+
* @param ast - Workflow to query
|
|
200
|
+
* @param nodeId - Optional node ID to filter connections
|
|
201
|
+
* @returns Array of connections
|
|
202
|
+
*
|
|
203
|
+
* @example
|
|
204
|
+
* ```typescript
|
|
205
|
+
* // Get all connections
|
|
206
|
+
* const allConnections = getConnections(workflow);
|
|
207
|
+
*
|
|
208
|
+
* // Get all connections involving a specific node
|
|
209
|
+
* const nodeConnections = getConnections(workflow, 'processor1');
|
|
210
|
+
* ```
|
|
211
|
+
*/
|
|
212
|
+
export function getConnections(ast, nodeId) {
|
|
213
|
+
if (!nodeId) {
|
|
214
|
+
return [...ast.connections];
|
|
215
|
+
}
|
|
216
|
+
return ast.connections.filter((conn) => conn.from.node === nodeId || conn.to.node === nodeId);
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Get all incoming connections to a node or port
|
|
220
|
+
*
|
|
221
|
+
* @param ast - Workflow to query
|
|
222
|
+
* @param nodeId - Target node ID
|
|
223
|
+
* @param portName - Optional port name to filter
|
|
224
|
+
* @returns Array of incoming connections
|
|
225
|
+
*
|
|
226
|
+
* @example
|
|
227
|
+
* ```typescript
|
|
228
|
+
* // Get all connections to a node
|
|
229
|
+
* const incoming = getIncomingConnections(workflow, 'processor1');
|
|
230
|
+
*
|
|
231
|
+
* // Get connections to specific port
|
|
232
|
+
* const inputConns = getIncomingConnections(workflow, 'processor1', 'input');
|
|
233
|
+
* ```
|
|
234
|
+
*/
|
|
235
|
+
export function getIncomingConnections(ast, nodeId, portName) {
|
|
236
|
+
return ast.connections.filter((conn) => {
|
|
237
|
+
if (conn.to.node !== nodeId) {
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
if (portName && conn.to.port !== portName) {
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
return true;
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Get all outgoing connections from a node or port
|
|
248
|
+
*
|
|
249
|
+
* @param ast - Workflow to query
|
|
250
|
+
* @param nodeId - Source node ID
|
|
251
|
+
* @param portName - Optional port name to filter
|
|
252
|
+
* @returns Array of outgoing connections
|
|
253
|
+
*
|
|
254
|
+
* @example
|
|
255
|
+
* ```typescript
|
|
256
|
+
* // Get all connections from a node
|
|
257
|
+
* const outgoing = getOutgoingConnections(workflow, 'processor1');
|
|
258
|
+
*
|
|
259
|
+
* // Get connections from specific port
|
|
260
|
+
* const outputConns = getOutgoingConnections(workflow, 'processor1', 'output');
|
|
261
|
+
* ```
|
|
262
|
+
*/
|
|
263
|
+
export function getOutgoingConnections(ast, nodeId, portName) {
|
|
264
|
+
return ast.connections.filter((conn) => {
|
|
265
|
+
if (conn.from.node !== nodeId) {
|
|
266
|
+
return false;
|
|
267
|
+
}
|
|
268
|
+
if (portName && conn.from.port !== portName) {
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
|
+
return true;
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Check if two ports are connected
|
|
276
|
+
*
|
|
277
|
+
* @param ast - Workflow to query
|
|
278
|
+
* @param from - Source port reference (string or object)
|
|
279
|
+
* @param to - Target port reference (string or object)
|
|
280
|
+
* @returns True if connected
|
|
281
|
+
*
|
|
282
|
+
* @example
|
|
283
|
+
* ```typescript
|
|
284
|
+
* if (isConnected(workflow, 'node1.output', 'node2.input')) {
|
|
285
|
+
* console.log('Nodes are connected');
|
|
286
|
+
* }
|
|
287
|
+
* ```
|
|
288
|
+
*/
|
|
289
|
+
export function isConnected(ast, from, to) {
|
|
290
|
+
const fromRef = typeof from === 'string' ? { node: from.split('.')[0], port: from.split('.')[1] } : from;
|
|
291
|
+
const toRef = typeof to === 'string' ? { node: to.split('.')[0], port: to.split('.')[1] } : to;
|
|
292
|
+
return ast.connections.some((conn) => portReferencesEqual(conn.from, fromRef) && portReferencesEqual(conn.to, toRef));
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Get all ports connected to a node
|
|
296
|
+
*
|
|
297
|
+
* @param ast - Workflow to query
|
|
298
|
+
* @param nodeId - Node ID to check
|
|
299
|
+
* @returns Object with incoming and outgoing port references
|
|
300
|
+
*
|
|
301
|
+
* @example
|
|
302
|
+
* ```typescript
|
|
303
|
+
* const ports = getConnectedPorts(workflow, 'processor1');
|
|
304
|
+
* console.log('Incoming:', ports.incoming);
|
|
305
|
+
* console.log('Outgoing:', ports.outgoing);
|
|
306
|
+
* ```
|
|
307
|
+
*/
|
|
308
|
+
export function getConnectedPorts(ast, nodeId) {
|
|
309
|
+
const incoming = ast.connections.filter((conn) => conn.to.node === nodeId).map((conn) => conn.to);
|
|
310
|
+
const outgoing = ast.connections
|
|
311
|
+
.filter((conn) => conn.from.node === nodeId)
|
|
312
|
+
.map((conn) => conn.from);
|
|
313
|
+
return { incoming, outgoing };
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Get all unconnected ports for a node
|
|
317
|
+
*
|
|
318
|
+
* @param ast - Workflow to query
|
|
319
|
+
* @param nodeId - Node ID to check
|
|
320
|
+
* @returns Object with unconnected input and output port names
|
|
321
|
+
*
|
|
322
|
+
* @example
|
|
323
|
+
* ```typescript
|
|
324
|
+
* const unconnected = getUnconnectedPorts(workflow, 'processor1');
|
|
325
|
+
* console.log('Unconnected inputs:', unconnected.inputs);
|
|
326
|
+
* console.log('Unconnected outputs:', unconnected.outputs);
|
|
327
|
+
* ```
|
|
328
|
+
*/
|
|
329
|
+
export function getUnconnectedPorts(ast, nodeId) {
|
|
330
|
+
const node = ast.instances.find((n) => n.id === nodeId);
|
|
331
|
+
if (!node) {
|
|
332
|
+
return { inputs: [], outputs: [] };
|
|
333
|
+
}
|
|
334
|
+
const nodeType = ast.nodeTypes.find((nt) => nt.name === node.nodeType || nt.functionName === node.nodeType);
|
|
335
|
+
if (!nodeType) {
|
|
336
|
+
return { inputs: [], outputs: [] };
|
|
337
|
+
}
|
|
338
|
+
// Get connected ports
|
|
339
|
+
const connectedInputs = new Set(ast.connections.filter((conn) => conn.to.node === nodeId).map((conn) => conn.to.port));
|
|
340
|
+
const connectedOutputs = new Set(ast.connections.filter((conn) => conn.from.node === nodeId).map((conn) => conn.from.port));
|
|
341
|
+
// Find unconnected ports
|
|
342
|
+
const inputs = Object.keys(nodeType.inputs).filter((port) => !connectedInputs.has(port));
|
|
343
|
+
const outputs = Object.keys(nodeType.outputs).filter((port) => !connectedOutputs.has(port));
|
|
344
|
+
return { inputs, outputs };
|
|
345
|
+
}
|
|
346
|
+
// ============================================================================
|
|
347
|
+
// DEPENDENCY ANALYSIS
|
|
348
|
+
// ============================================================================
|
|
349
|
+
/**
|
|
350
|
+
* Get direct dependencies of a node (nodes that feed into it)
|
|
351
|
+
*
|
|
352
|
+
* @param ast - Workflow to query
|
|
353
|
+
* @param nodeId - Node ID to analyze
|
|
354
|
+
* @returns Array of node IDs that this node depends on
|
|
355
|
+
*
|
|
356
|
+
* @example
|
|
357
|
+
* ```typescript
|
|
358
|
+
* const deps = getDependencies(workflow, 'processor1');
|
|
359
|
+
* console.log('Direct dependencies:', deps);
|
|
360
|
+
* ```
|
|
361
|
+
*/
|
|
362
|
+
export function getDependencies(ast, nodeId) {
|
|
363
|
+
const deps = new Set();
|
|
364
|
+
getMainFlowConnections(ast).forEach((conn) => {
|
|
365
|
+
if (conn.to.node === nodeId && conn.from.node !== 'Start') {
|
|
366
|
+
deps.add(conn.from.node);
|
|
367
|
+
}
|
|
368
|
+
});
|
|
369
|
+
return Array.from(deps);
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Get data-only dependencies of a node (excludes control flow connections)
|
|
373
|
+
*
|
|
374
|
+
* @param ast - Workflow to query
|
|
375
|
+
* @param nodeId - Node ID to analyze
|
|
376
|
+
* @returns Array of node IDs that provide data inputs to this node
|
|
377
|
+
*/
|
|
378
|
+
export function getDataDependencies(ast, nodeId) {
|
|
379
|
+
const deps = new Set();
|
|
380
|
+
const instanceTypeMap = new Map();
|
|
381
|
+
for (const inst of ast.instances) {
|
|
382
|
+
// Check both name (for npm nodes like 'npm/pkg/func') and functionName (for local nodes)
|
|
383
|
+
const nt = ast.nodeTypes.find((t) => t.name === inst.nodeType || t.functionName === inst.nodeType);
|
|
384
|
+
if (nt)
|
|
385
|
+
instanceTypeMap.set(inst.id, nt);
|
|
386
|
+
}
|
|
387
|
+
getMainFlowConnections(ast).forEach((conn) => {
|
|
388
|
+
if (conn.to.node === nodeId) {
|
|
389
|
+
if (conn.from.node === 'Start') {
|
|
390
|
+
// Include Start only when it provides data (not just execute)
|
|
391
|
+
if (conn.from.port !== 'execute') {
|
|
392
|
+
deps.add(conn.from.node);
|
|
393
|
+
}
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
const sourceNodeType = instanceTypeMap.get(conn.from.node);
|
|
397
|
+
if (sourceNodeType) {
|
|
398
|
+
const sourcePort = sourceNodeType.outputs[conn.from.port];
|
|
399
|
+
if (sourcePort && (sourcePort.isControlFlow || sourcePort.dataType === 'STEP')) {
|
|
400
|
+
return; // Skip control flow connections
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
deps.add(conn.from.node);
|
|
404
|
+
}
|
|
405
|
+
});
|
|
406
|
+
return Array.from(deps);
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Get direct dependents of a node (nodes that consume its output)
|
|
410
|
+
*
|
|
411
|
+
* @param ast - Workflow to query
|
|
412
|
+
* @param nodeId - Node ID to analyze
|
|
413
|
+
* @returns Array of node IDs that depend on this node
|
|
414
|
+
*
|
|
415
|
+
* @example
|
|
416
|
+
* ```typescript
|
|
417
|
+
* const dependents = getDependents(workflow, 'processor1');
|
|
418
|
+
* console.log('Direct dependents:', dependents);
|
|
419
|
+
* ```
|
|
420
|
+
*/
|
|
421
|
+
export function getDependents(ast, nodeId) {
|
|
422
|
+
const dependents = new Set();
|
|
423
|
+
getMainFlowConnections(ast).forEach((conn) => {
|
|
424
|
+
if (conn.from.node === nodeId && conn.to.node !== 'Exit') {
|
|
425
|
+
dependents.add(conn.to.node);
|
|
426
|
+
}
|
|
427
|
+
});
|
|
428
|
+
return Array.from(dependents);
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Get transitive dependencies (all upstream nodes)
|
|
432
|
+
*
|
|
433
|
+
* @param ast - Workflow to query
|
|
434
|
+
* @param nodeId - Node ID to analyze
|
|
435
|
+
* @returns Array of all node IDs in the dependency chain
|
|
436
|
+
*
|
|
437
|
+
* @example
|
|
438
|
+
* ```typescript
|
|
439
|
+
* const allDeps = getTransitiveDependencies(workflow, 'finalProcessor');
|
|
440
|
+
* console.log('All upstream nodes:', allDeps);
|
|
441
|
+
* ```
|
|
442
|
+
*/
|
|
443
|
+
export function getTransitiveDependencies(ast, nodeId) {
|
|
444
|
+
const visited = new Set();
|
|
445
|
+
const queue = [nodeId];
|
|
446
|
+
while (queue.length > 0) {
|
|
447
|
+
const current = queue.shift();
|
|
448
|
+
if (visited.has(current)) {
|
|
449
|
+
continue;
|
|
450
|
+
}
|
|
451
|
+
visited.add(current);
|
|
452
|
+
const deps = getDependencies(ast, current);
|
|
453
|
+
deps.forEach((dep) => {
|
|
454
|
+
if (!visited.has(dep)) {
|
|
455
|
+
queue.push(dep);
|
|
456
|
+
}
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
// Remove the original node from results
|
|
460
|
+
visited.delete(nodeId);
|
|
461
|
+
return Array.from(visited);
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* Find a path between two nodes (BFS)
|
|
465
|
+
*
|
|
466
|
+
* @param ast - Workflow to query
|
|
467
|
+
* @param fromNodeId - Source node ID
|
|
468
|
+
* @param toNodeId - Target node ID
|
|
469
|
+
* @returns Array of node IDs representing the path, or null if no path exists
|
|
470
|
+
*
|
|
471
|
+
* @example
|
|
472
|
+
* ```typescript
|
|
473
|
+
* const path = findPath(workflow, 'input', 'output');
|
|
474
|
+
* if (path) {
|
|
475
|
+
* console.log('Path:', path.join(' → '));
|
|
476
|
+
* } else {
|
|
477
|
+
* console.log('No path exists');
|
|
478
|
+
* }
|
|
479
|
+
* ```
|
|
480
|
+
*/
|
|
481
|
+
export function findPath(ast, fromNodeId, toNodeId) {
|
|
482
|
+
if (fromNodeId === toNodeId) {
|
|
483
|
+
return [fromNodeId];
|
|
484
|
+
}
|
|
485
|
+
const visited = new Set();
|
|
486
|
+
const queue = [{ node: fromNodeId, path: [fromNodeId] }];
|
|
487
|
+
while (queue.length > 0) {
|
|
488
|
+
const { node: current, path } = queue.shift();
|
|
489
|
+
if (visited.has(current)) {
|
|
490
|
+
continue;
|
|
491
|
+
}
|
|
492
|
+
visited.add(current);
|
|
493
|
+
// Check if we reached the target
|
|
494
|
+
if (current === toNodeId) {
|
|
495
|
+
return path;
|
|
496
|
+
}
|
|
497
|
+
// Add all dependents to queue
|
|
498
|
+
const dependents = getDependents(ast, current);
|
|
499
|
+
dependents.forEach((dep) => {
|
|
500
|
+
if (!visited.has(dep)) {
|
|
501
|
+
queue.push({ node: dep, path: [...path, dep] });
|
|
502
|
+
}
|
|
503
|
+
});
|
|
504
|
+
}
|
|
505
|
+
return null; // No path found
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* Get topological order of all nodes (for execution planning)
|
|
509
|
+
*
|
|
510
|
+
* @param ast - Workflow to query
|
|
511
|
+
* @returns Array of node IDs in topological order
|
|
512
|
+
* @throws {Error} If workflow contains cycles
|
|
513
|
+
*
|
|
514
|
+
* @example
|
|
515
|
+
* ```typescript
|
|
516
|
+
* try {
|
|
517
|
+
* const order = getTopologicalOrder(workflow);
|
|
518
|
+
* console.log('Execution order:', order);
|
|
519
|
+
* } catch (error) {
|
|
520
|
+
* console.error('Workflow has cycles!');
|
|
521
|
+
* }
|
|
522
|
+
* ```
|
|
523
|
+
*/
|
|
524
|
+
export function getTopologicalOrder(ast) {
|
|
525
|
+
const mainInstances = getMainFlowInstances(ast);
|
|
526
|
+
const mainConnections = getMainFlowConnections(ast);
|
|
527
|
+
const inDegree = new Map();
|
|
528
|
+
const adjacency = new Map();
|
|
529
|
+
// Initialize with main-flow instances only
|
|
530
|
+
mainInstances.forEach((node) => {
|
|
531
|
+
inDegree.set(node.id, 0);
|
|
532
|
+
adjacency.set(node.id, []);
|
|
533
|
+
});
|
|
534
|
+
// Build graph from main-flow connections only
|
|
535
|
+
mainConnections.forEach((conn) => {
|
|
536
|
+
if (conn.from.node !== 'Start' && conn.to.node !== 'Exit') {
|
|
537
|
+
const from = conn.from.node;
|
|
538
|
+
const to = conn.to.node;
|
|
539
|
+
adjacency.get(from)?.push(to);
|
|
540
|
+
inDegree.set(to, (inDegree.get(to) || 0) + 1);
|
|
541
|
+
}
|
|
542
|
+
});
|
|
543
|
+
// Kahn's algorithm
|
|
544
|
+
const queue = [];
|
|
545
|
+
const result = [];
|
|
546
|
+
// Start with nodes that have no dependencies
|
|
547
|
+
inDegree.forEach((degree, node) => {
|
|
548
|
+
if (degree === 0) {
|
|
549
|
+
queue.push(node);
|
|
550
|
+
}
|
|
551
|
+
});
|
|
552
|
+
while (queue.length > 0) {
|
|
553
|
+
const current = queue.shift();
|
|
554
|
+
result.push(current);
|
|
555
|
+
const neighbors = adjacency.get(current) || [];
|
|
556
|
+
neighbors.forEach((neighbor) => {
|
|
557
|
+
const newDegree = (inDegree.get(neighbor) || 0) - 1;
|
|
558
|
+
inDegree.set(neighbor, newDegree);
|
|
559
|
+
if (newDegree === 0) {
|
|
560
|
+
queue.push(neighbor);
|
|
561
|
+
}
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
// Check for cycles (compare against main-flow instances, not all instances)
|
|
565
|
+
if (result.length !== mainInstances.length) {
|
|
566
|
+
throw new Error('Cannot compute topological order: workflow contains cycles');
|
|
567
|
+
}
|
|
568
|
+
return result;
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Group nodes by execution level (nodes at same level can execute in parallel)
|
|
572
|
+
*
|
|
573
|
+
* @param ast - Workflow to query
|
|
574
|
+
* @returns Array of arrays, where each sub-array contains node IDs at that level
|
|
575
|
+
* @throws {Error} If workflow contains cycles
|
|
576
|
+
*
|
|
577
|
+
* @example
|
|
578
|
+
* ```typescript
|
|
579
|
+
* const groups = getExecutionGroups(workflow);
|
|
580
|
+
* groups.forEach((group, level) => {
|
|
581
|
+
* console.log(`Level ${level}:`, group.join(', '));
|
|
582
|
+
* });
|
|
583
|
+
* ```
|
|
584
|
+
*/
|
|
585
|
+
export function getExecutionGroups(ast) {
|
|
586
|
+
const mainInstances = getMainFlowInstances(ast);
|
|
587
|
+
const mainConnections = getMainFlowConnections(ast);
|
|
588
|
+
const inDegree = new Map();
|
|
589
|
+
const adjacency = new Map();
|
|
590
|
+
// Initialize with main-flow instances only
|
|
591
|
+
mainInstances.forEach((node) => {
|
|
592
|
+
inDegree.set(node.id, 0);
|
|
593
|
+
adjacency.set(node.id, []);
|
|
594
|
+
});
|
|
595
|
+
// Build graph from main-flow connections only
|
|
596
|
+
mainConnections.forEach((conn) => {
|
|
597
|
+
if (conn.from.node !== 'Start' && conn.to.node !== 'Exit') {
|
|
598
|
+
const from = conn.from.node;
|
|
599
|
+
const to = conn.to.node;
|
|
600
|
+
adjacency.get(from)?.push(to);
|
|
601
|
+
inDegree.set(to, (inDegree.get(to) || 0) + 1);
|
|
602
|
+
}
|
|
603
|
+
});
|
|
604
|
+
// Level-based BFS
|
|
605
|
+
const groups = [];
|
|
606
|
+
let currentLevel = Array.from(inDegree.entries())
|
|
607
|
+
.filter(([_, degree]) => degree === 0)
|
|
608
|
+
.map(([node, _]) => node);
|
|
609
|
+
const processed = new Set();
|
|
610
|
+
while (currentLevel.length > 0) {
|
|
611
|
+
groups.push([...currentLevel]);
|
|
612
|
+
const nextLevel = new Set();
|
|
613
|
+
currentLevel.forEach((node) => {
|
|
614
|
+
processed.add(node);
|
|
615
|
+
const neighbors = adjacency.get(node) || [];
|
|
616
|
+
neighbors.forEach((neighbor) => {
|
|
617
|
+
const newDegree = (inDegree.get(neighbor) || 0) - 1;
|
|
618
|
+
inDegree.set(neighbor, newDegree);
|
|
619
|
+
if (newDegree === 0 && !processed.has(neighbor)) {
|
|
620
|
+
nextLevel.add(neighbor);
|
|
621
|
+
}
|
|
622
|
+
});
|
|
623
|
+
});
|
|
624
|
+
currentLevel = Array.from(nextLevel);
|
|
625
|
+
}
|
|
626
|
+
// Check for cycles (compare against main-flow instances, not all instances)
|
|
627
|
+
if (processed.size !== mainInstances.length) {
|
|
628
|
+
throw new Error('Cannot compute execution groups: workflow contains cycles');
|
|
629
|
+
}
|
|
630
|
+
return groups;
|
|
631
|
+
}
|
|
632
|
+
// ============================================================================
|
|
633
|
+
// STATISTICS
|
|
634
|
+
// ============================================================================
|
|
635
|
+
/**
|
|
636
|
+
* Count nodes, optionally filtered
|
|
637
|
+
*
|
|
638
|
+
* @param ast - Workflow to query
|
|
639
|
+
* @param filter - Optional filter criteria
|
|
640
|
+
* @returns Number of matching nodes
|
|
641
|
+
*
|
|
642
|
+
* @example
|
|
643
|
+
* ```typescript
|
|
644
|
+
* const total = countNodes(workflow);
|
|
645
|
+
* const processors = countNodes(workflow, { type: 'process' });
|
|
646
|
+
* ```
|
|
647
|
+
*/
|
|
648
|
+
export function countNodes(ast, filter) {
|
|
649
|
+
return getNodes(ast, filter).length;
|
|
650
|
+
}
|
|
651
|
+
/**
|
|
652
|
+
* Count connections, optionally for a specific node
|
|
653
|
+
*
|
|
654
|
+
* @param ast - Workflow to query
|
|
655
|
+
* @param nodeId - Optional node ID to filter
|
|
656
|
+
* @returns Number of connections
|
|
657
|
+
*
|
|
658
|
+
* @example
|
|
659
|
+
* ```typescript
|
|
660
|
+
* const total = countConnections(workflow);
|
|
661
|
+
* const nodeConns = countConnections(workflow, 'processor1');
|
|
662
|
+
* ```
|
|
663
|
+
*/
|
|
664
|
+
export function countConnections(ast, nodeId) {
|
|
665
|
+
return getConnections(ast, nodeId).length;
|
|
666
|
+
}
|
|
667
|
+
/**
|
|
668
|
+
* Count node types defined in workflow
|
|
669
|
+
*
|
|
670
|
+
* @param ast - Workflow to query
|
|
671
|
+
* @returns Number of node type definitions
|
|
672
|
+
*
|
|
673
|
+
* @example
|
|
674
|
+
* ```typescript
|
|
675
|
+
* const typeCount = countNodeTypes(workflow);
|
|
676
|
+
* ```
|
|
677
|
+
*/
|
|
678
|
+
export function countNodeTypes(ast) {
|
|
679
|
+
return ast.nodeTypes.length;
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* Find isolated nodes (no connections)
|
|
683
|
+
*
|
|
684
|
+
* @param ast - Workflow to query
|
|
685
|
+
* @returns Array of isolated node IDs
|
|
686
|
+
*
|
|
687
|
+
* @example
|
|
688
|
+
* ```typescript
|
|
689
|
+
* const isolated = findIsolatedNodes(workflow);
|
|
690
|
+
* if (isolated.length > 0) {
|
|
691
|
+
* console.warn('Isolated nodes:', isolated);
|
|
692
|
+
* }
|
|
693
|
+
* ```
|
|
694
|
+
*/
|
|
695
|
+
export function findIsolatedNodes(ast) {
|
|
696
|
+
const mainConnections = getMainFlowConnections(ast);
|
|
697
|
+
return getMainFlowInstances(ast)
|
|
698
|
+
.filter((node) => {
|
|
699
|
+
const hasConnections = mainConnections.some((conn) => conn.from.node === node.id || conn.to.node === node.id);
|
|
700
|
+
return !hasConnections;
|
|
701
|
+
})
|
|
702
|
+
.map((node) => node.id);
|
|
703
|
+
}
|
|
704
|
+
/**
|
|
705
|
+
* Find unused node types (no instances)
|
|
706
|
+
*
|
|
707
|
+
* @param ast - Workflow to query
|
|
708
|
+
* @returns Array of unused node type names
|
|
709
|
+
*
|
|
710
|
+
* @example
|
|
711
|
+
* ```typescript
|
|
712
|
+
* const unused = findUnusedNodeTypes(workflow);
|
|
713
|
+
* if (unused.length > 0) {
|
|
714
|
+
* console.warn('Unused node types:', unused);
|
|
715
|
+
* }
|
|
716
|
+
* ```
|
|
717
|
+
*/
|
|
718
|
+
export function findUnusedNodeTypes(ast) {
|
|
719
|
+
const usedTypes = new Set(ast.instances.map((n) => n.nodeType));
|
|
720
|
+
return ast.nodeTypes.filter((nt) => !usedTypes.has(nt.functionName)).map((nt) => nt.name);
|
|
721
|
+
}
|
|
722
|
+
/**
|
|
723
|
+
* Find dead-end nodes (output never reaches Exit)
|
|
724
|
+
*
|
|
725
|
+
* @param ast - Workflow to query
|
|
726
|
+
* @returns Array of dead-end node IDs
|
|
727
|
+
*
|
|
728
|
+
* @example
|
|
729
|
+
* ```typescript
|
|
730
|
+
* const deadEnds = findDeadEnds(workflow);
|
|
731
|
+
* if (deadEnds.length > 0) {
|
|
732
|
+
* console.warn('Dead-end nodes:', deadEnds);
|
|
733
|
+
* }
|
|
734
|
+
* ```
|
|
735
|
+
*/
|
|
736
|
+
export function findDeadEnds(ast) {
|
|
737
|
+
const deadEnds = [];
|
|
738
|
+
const mainConnections = getMainFlowConnections(ast);
|
|
739
|
+
getMainFlowInstances(ast).forEach((node) => {
|
|
740
|
+
// Check if there's a path from this node to Exit
|
|
741
|
+
const hasPathToExit = mainConnections.some((conn) => {
|
|
742
|
+
if (conn.from.node === node.id && conn.to.node === 'Exit') {
|
|
743
|
+
return true;
|
|
744
|
+
}
|
|
745
|
+
// Check indirect paths via DFS
|
|
746
|
+
const visited = new Set();
|
|
747
|
+
const stack = [node.id];
|
|
748
|
+
while (stack.length > 0) {
|
|
749
|
+
const current = stack.pop();
|
|
750
|
+
if (visited.has(current)) {
|
|
751
|
+
continue;
|
|
752
|
+
}
|
|
753
|
+
visited.add(current);
|
|
754
|
+
// Check if current connects to Exit (using main flow connections)
|
|
755
|
+
const toExit = mainConnections.some((c) => c.from.node === current && c.to.node === 'Exit');
|
|
756
|
+
if (toExit) {
|
|
757
|
+
return true;
|
|
758
|
+
}
|
|
759
|
+
// Add dependents to stack (getDependents already uses main flow connections)
|
|
760
|
+
const deps = getDependents(ast, current);
|
|
761
|
+
deps.forEach((dep) => stack.push(dep));
|
|
762
|
+
}
|
|
763
|
+
return false;
|
|
764
|
+
});
|
|
765
|
+
if (!hasPathToExit) {
|
|
766
|
+
deadEnds.push(node.id);
|
|
767
|
+
}
|
|
768
|
+
});
|
|
769
|
+
return deadEnds;
|
|
770
|
+
}
|
|
771
|
+
/**
|
|
772
|
+
* Find output ports that are not connected to anything.
|
|
773
|
+
* Excludes control flow ports (onSuccess/onFailure) and scoped ports.
|
|
774
|
+
*
|
|
775
|
+
* @param ast - Workflow to query
|
|
776
|
+
* @returns Array of objects with nodeId and their disconnected output port names
|
|
777
|
+
*/
|
|
778
|
+
/**
|
|
779
|
+
* Find dead-end details: both dead-end nodes and disconnected output ports.
|
|
780
|
+
* Combines findDeadEnds() and findDisconnectedOutputPorts() into a single result.
|
|
781
|
+
*
|
|
782
|
+
* @param ast - Workflow to query
|
|
783
|
+
* @returns Object with deadEndNodes and disconnectedOutputs
|
|
784
|
+
*/
|
|
785
|
+
export function findDeadEndDetails(ast) {
|
|
786
|
+
return {
|
|
787
|
+
deadEndNodes: findDeadEnds(ast),
|
|
788
|
+
disconnectedOutputs: findDisconnectedOutputPorts(ast),
|
|
789
|
+
};
|
|
790
|
+
}
|
|
791
|
+
export function findDisconnectedOutputPorts(ast) {
|
|
792
|
+
const connectedOutputPorts = new Set();
|
|
793
|
+
getMainFlowConnections(ast).forEach((conn) => {
|
|
794
|
+
connectedOutputPorts.add(`${conn.from.node}.${conn.from.port}`);
|
|
795
|
+
});
|
|
796
|
+
const results = [];
|
|
797
|
+
for (const instance of getMainFlowInstances(ast)) {
|
|
798
|
+
// Check both name (for npm nodes like 'npm/pkg/func') and functionName (for local nodes)
|
|
799
|
+
const nodeType = ast.nodeTypes.find((nt) => nt.name === instance.nodeType || nt.functionName === instance.nodeType);
|
|
800
|
+
if (!nodeType)
|
|
801
|
+
continue;
|
|
802
|
+
const disconnectedPorts = [];
|
|
803
|
+
for (const [portName, portDef] of Object.entries(nodeType.outputs)) {
|
|
804
|
+
if (portDef.isControlFlow || portDef.failure || portDef.scope)
|
|
805
|
+
continue;
|
|
806
|
+
if (!connectedOutputPorts.has(`${instance.id}.${portName}`)) {
|
|
807
|
+
disconnectedPorts.push(portName);
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
if (disconnectedPorts.length > 0) {
|
|
811
|
+
results.push({ nodeId: instance.id, ports: disconnectedPorts });
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
return results;
|
|
815
|
+
}
|
|
816
|
+
//# sourceMappingURL=query.js.map
|