@ai-setting/roy-agent-core 1.3.10 → 1.3.14
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/dist/config/index.js +1647 -0
- package/dist/index.js +12579 -89691
- package/package.json +19 -56
- package/src/config/config-component.test.ts +0 -627
- package/src/config/config-component.ts +0 -906
- package/src/config/config-parser.test.ts +0 -319
- package/src/config/config-parser.ts +0 -203
- package/src/config/decentralized-config.test.ts +0 -740
- package/src/config/env-key.ts +0 -210
- package/src/config/env-source.test.ts +0 -252
- package/src/config/env-source.ts +0 -301
- package/src/config/file-source.test.ts +0 -357
- package/src/config/file-source.ts +0 -421
- package/src/config/index.ts +0 -24
- package/src/config/protocol-resolver.test.ts +0 -217
- package/src/config/protocol-resolver.ts +0 -228
- package/src/env/agent/agent-component.abort.test.ts +0 -511
- package/src/env/agent/agent-component.record-session.test.ts +0 -349
- package/src/env/agent/agent-component.test.ts +0 -1389
- package/src/env/agent/agent-component.tool-error.test.ts +0 -327
- package/src/env/agent/agent-component.ts +0 -1711
- package/src/env/agent/agent-config-registration.test.ts +0 -226
- package/src/env/agent/agent-config-registration.ts +0 -46
- package/src/env/agent/agent-reminder-plugin.integration.test.ts +0 -243
- package/src/env/agent/index.ts +0 -10
- package/src/env/agent/summary-agent.parse-hint.test.ts +0 -360
- package/src/env/agent/summary-agent.ts +0 -508
- package/src/env/agent/types.ts +0 -536
- package/src/env/commands/commands-component.test.ts +0 -364
- package/src/env/commands/commands-component.ts +0 -604
- package/src/env/commands/commands-config-registration.test.ts +0 -198
- package/src/env/commands/commands-config-registration.ts +0 -38
- package/src/env/commands/index.ts +0 -21
- package/src/env/commands/parser.test.ts +0 -203
- package/src/env/commands/parser.ts +0 -115
- package/src/env/commands/types.ts +0 -184
- package/src/env/commands-prompt-integration.test.ts +0 -243
- package/src/env/component-env.test.ts +0 -119
- package/src/env/component.ts +0 -335
- package/src/env/constants.test.ts +0 -72
- package/src/env/constants.ts +0 -123
- package/src/env/debug/debug-component.test.ts +0 -114
- package/src/env/debug/debug-component.ts +0 -547
- package/src/env/debug/formatters/index.ts +0 -9
- package/src/env/debug/formatters/repl-formatter.test.ts +0 -139
- package/src/env/debug/formatters/repl-formatter.ts +0 -358
- package/src/env/debug/formatters/trace-formatter.test.ts +0 -119
- package/src/env/debug/formatters/trace-formatter.ts +0 -191
- package/src/env/debug/formatters/tree-formatter.test.ts +0 -107
- package/src/env/debug/formatters/tree-formatter.ts +0 -325
- package/src/env/debug/index.ts +0 -38
- package/src/env/debug/parser/regex-parser.test.ts +0 -201
- package/src/env/debug/parser/regex-parser.ts +0 -196
- package/src/env/debug/parser/span-builder.test.ts +0 -241
- package/src/env/debug/parser/span-builder.ts +0 -386
- package/src/env/debug/reader/log-reader.test.ts +0 -170
- package/src/env/debug/reader/log-reader.ts +0 -186
- package/src/env/debug/reader/span-db-reader.test.ts +0 -118
- package/src/env/debug/reader/span-db-reader.ts +0 -201
- package/src/env/debug/types.test.ts +0 -187
- package/src/env/debug/types.ts +0 -171
- package/src/env/environment-init.test.ts +0 -183
- package/src/env/environment-lifecycle.test.ts +0 -516
- package/src/env/environment-service.test.ts +0 -332
- package/src/env/environment.handle-query.test.ts +0 -96
- package/src/env/environment.test.ts +0 -232
- package/src/env/environment.ts +0 -708
- package/src/env/errors.test.ts +0 -165
- package/src/env/errors.ts +0 -157
- package/src/env/event-source/event-source-agent-handler.test.ts +0 -193
- package/src/env/event-source/event-source-agent-handler.ts +0 -111
- package/src/env/event-source/event-source-component.process-cleanup.test.ts +0 -236
- package/src/env/event-source/event-source-component.stop.test.ts +0 -346
- package/src/env/event-source/event-source-component.test.ts +0 -1207
- package/src/env/event-source/event-source-component.ts +0 -1379
- package/src/env/event-source/event-source-config-registration.test.ts +0 -242
- package/src/env/event-source/event-source-config-registration.ts +0 -37
- package/src/env/event-source/event-source-integration.test.ts +0 -320
- package/src/env/event-source/event-source-platform.test.ts +0 -630
- package/src/env/event-source/types.ts +0 -298
- package/src/env/hook/global-hook-manager.ts +0 -162
- package/src/env/hook/hook-manager.test.ts +0 -374
- package/src/env/hook/hook-manager.ts +0 -309
- package/src/env/hook/index.ts +0 -38
- package/src/env/hook/types.ts +0 -138
- package/src/env/index.ts +0 -144
- package/src/env/interface.ts +0 -203
- package/src/env/llm/hooks.test.ts +0 -293
- package/src/env/llm/hooks.ts +0 -316
- package/src/env/llm/index.ts +0 -61
- package/src/env/llm/invoke-threshold-check.test.ts +0 -88
- package/src/env/llm/invoke-timeout.test.ts +0 -54
- package/src/env/llm/invoke.test.ts +0 -71
- package/src/env/llm/invoke.ts +0 -1039
- package/src/env/llm/llm-config.test.ts +0 -523
- package/src/env/llm/llm.test.ts +0 -233
- package/src/env/llm/llm.ts +0 -568
- package/src/env/llm/provider.test.ts +0 -182
- package/src/env/llm/provider.ts +0 -108
- package/src/env/llm/transform.test.ts +0 -251
- package/src/env/llm/transform.ts +0 -286
- package/src/env/llm/types.test.ts +0 -580
- package/src/env/llm/types.ts +0 -424
- package/src/env/log-trace/decorator-otel.test.ts +0 -182
- package/src/env/log-trace/decorator.ts +0 -230
- package/src/env/log-trace/index.ts +0 -79
- package/src/env/log-trace/log-trace-component.test.ts +0 -242
- package/src/env/log-trace/log-trace-component.ts +0 -497
- package/src/env/log-trace/log-trace-config-registration.test.ts +0 -348
- package/src/env/log-trace/log-trace-config-registration.ts +0 -45
- package/src/env/log-trace/logger.test.ts +0 -149
- package/src/env/log-trace/logger.ts +0 -522
- package/src/env/log-trace/opentelemetry/cli-propagation.test.ts +0 -147
- package/src/env/log-trace/opentelemetry/cli-propagation.ts +0 -194
- package/src/env/log-trace/opentelemetry/integration.test.ts +0 -668
- package/src/env/log-trace/opentelemetry/mod.ts +0 -25
- package/src/env/log-trace/opentelemetry/propagation-env.test.ts +0 -181
- package/src/env/log-trace/opentelemetry/propagation-env.ts +0 -136
- package/src/env/log-trace/opentelemetry/propagation.test.ts +0 -259
- package/src/env/log-trace/opentelemetry/propagation.ts +0 -215
- package/src/env/log-trace/opentelemetry/tracer-provider-context.test.ts +0 -166
- package/src/env/log-trace/opentelemetry/tracer-provider.test.ts +0 -379
- package/src/env/log-trace/opentelemetry/tracer-provider.ts +0 -612
- package/src/env/log-trace/span-storage.test.ts +0 -145
- package/src/env/log-trace/span-storage.ts +0 -230
- package/src/env/log-trace/trace-context.test.ts +0 -187
- package/src/env/log-trace/trace-context.ts +0 -162
- package/src/env/log-trace/types.test.ts +0 -63
- package/src/env/log-trace/types.ts +0 -172
- package/src/env/mcp/README.md +0 -244
- package/src/env/mcp/__integration__/mcp-component.integration.test.ts +0 -373
- package/src/env/mcp/config.test.ts +0 -74
- package/src/env/mcp/config.ts +0 -116
- package/src/env/mcp/index.ts +0 -41
- package/src/env/mcp/loader.test.ts +0 -161
- package/src/env/mcp/loader.ts +0 -209
- package/src/env/mcp/mcp-component.test.ts +0 -111
- package/src/env/mcp/mcp-component.ts +0 -358
- package/src/env/mcp/mcp-config-registration.test.ts +0 -304
- package/src/env/mcp/mcp-config-registration.ts +0 -50
- package/src/env/mcp/scanner.test.ts +0 -170
- package/src/env/mcp/scanner.ts +0 -246
- package/src/env/mcp/tool/adapter.test.ts +0 -520
- package/src/env/mcp/tool/adapter.ts +0 -521
- package/src/env/mcp/tool/index.ts +0 -5
- package/src/env/mcp/types.test.ts +0 -171
- package/src/env/mcp/types.ts +0 -79
- package/src/env/memory/README.md +0 -177
- package/src/env/memory/built-in/index.ts +0 -59
- package/src/env/memory/built-in/recall-memory.ts +0 -103
- package/src/env/memory/built-in/record-memory.ts +0 -148
- package/src/env/memory/index.ts +0 -20
- package/src/env/memory/memory-component.test.ts +0 -239
- package/src/env/memory/memory-component.ts +0 -503
- package/src/env/memory/memory-config-registration.test.ts +0 -67
- package/src/env/memory/memory-config-registration.ts +0 -48
- package/src/env/memory/memory-config.ts +0 -45
- package/src/env/memory/memory-file.test.ts +0 -268
- package/src/env/memory/plugin/index.ts +0 -48
- package/src/env/memory/plugin/memory-agent.test.ts +0 -249
- package/src/env/memory/plugin/memory-agent.ts +0 -365
- package/src/env/memory/plugin/memory-manager.ts +0 -198
- package/src/env/memory/plugin/memory-plugin-agent.test.ts +0 -145
- package/src/env/memory/plugin/memory-plugin.ts +0 -210
- package/src/env/memory/plugin/plugin-simplified.test.ts +0 -51
- package/src/env/memory/plugin/recall-memory.test.ts +0 -106
- package/src/env/memory/plugin/recall-memory.ts +0 -53
- package/src/env/memory/plugin/types.ts +0 -101
- package/src/env/memory/tools/memory-agent-tools.ts +0 -228
- package/src/env/memory/types.ts +0 -85
- package/src/env/paths.ts +0 -118
- package/src/env/prompt/index.ts +0 -18
- package/src/env/prompt/memory-prompts.test.ts +0 -91
- package/src/env/prompt/prompt-component.test.ts +0 -491
- package/src/env/prompt/prompt-component.ts +0 -619
- package/src/env/prompt/prompt-config-registration.test.ts +0 -213
- package/src/env/prompt/prompt-config-registration.ts +0 -39
- package/src/env/prompt/prompts-index.ts +0 -504
- package/src/env/prompt/renderer.ts +0 -67
- package/src/env/prompt/types.ts +0 -136
- package/src/env/session/hooks.ts +0 -18
- package/src/env/session/index.ts +0 -37
- package/src/env/session/search-query-parser.test.ts +0 -425
- package/src/env/session/search-query-parser.ts +0 -171
- package/src/env/session/session-checkpoint.test.ts +0 -523
- package/src/env/session/session-component.extract-recent-messages.test.ts +0 -209
- package/src/env/session/session-component.test.ts +0 -132
- package/src/env/session/session-component.ts +0 -1249
- package/src/env/session/session-config-registration.test.ts +0 -138
- package/src/env/session/session-config-registration.ts +0 -52
- package/src/env/session/session-message-converter.test.ts +0 -763
- package/src/env/session/session-message-converter.ts +0 -415
- package/src/env/session/session-message-e2e.test.ts +0 -448
- package/src/env/session/session-search.test.ts +0 -391
- package/src/env/session/session-store.test.ts +0 -362
- package/src/env/session/session-store.ts +0 -141
- package/src/env/session/storage/index.ts +0 -6
- package/src/env/session/storage/memory.ts +0 -502
- package/src/env/session/storage/sqlite.ts +0 -794
- package/src/env/session/types.ts +0 -742
- package/src/env/skill/config.ts +0 -39
- package/src/env/skill/index.ts +0 -6
- package/src/env/skill/parser.test.ts +0 -116
- package/src/env/skill/parser.ts +0 -77
- package/src/env/skill/scanner.test.ts +0 -211
- package/src/env/skill/scanner.ts +0 -119
- package/src/env/skill/skill-component.test.ts +0 -234
- package/src/env/skill/skill-component.ts +0 -352
- package/src/env/skill/skill-config-registration.test.ts +0 -60
- package/src/env/skill/skill-config-registration.ts +0 -43
- package/src/env/skill/tool/index.ts +0 -1
- package/src/env/skill/tool/skill-tool.test.ts +0 -100
- package/src/env/skill/tool/skill-tool.ts +0 -72
- package/src/env/skill/types.ts +0 -64
- package/src/env/task/delegate/delegate-tool.test.ts +0 -498
- package/src/env/task/delegate/delegate-tool.ts +0 -1014
- package/src/env/task/delegate/index.ts +0 -18
- package/src/env/task/delegate/stop-tool.test.ts +0 -140
- package/src/env/task/delegate/stop-tool.ts +0 -119
- package/src/env/task/delegate/task-events.test.ts +0 -178
- package/src/env/task/delegate/task-events.ts +0 -143
- package/src/env/task/hooks/contexts.test.ts +0 -92
- package/src/env/task/hooks/contexts.ts +0 -192
- package/src/env/task/hooks/index.ts +0 -23
- package/src/env/task/hooks/task-hook-points.test.ts +0 -32
- package/src/env/task/hooks/task-hook-points.ts +0 -54
- package/src/env/task/index.ts +0 -7
- package/src/env/task/plugins/index.ts +0 -13
- package/src/env/task/plugins/task-plugin.test.ts +0 -74
- package/src/env/task/plugins/task-plugin.ts +0 -89
- package/src/env/task/plugins/task-tag-plugin.test.ts +0 -377
- package/src/env/task/plugins/task-tag-plugin.ts +0 -319
- package/src/env/task/plugins/task-workflow-extractor.integration.test.ts +0 -226
- package/src/env/task/plugins/workflow-extractor-agent.test.ts +0 -107
- package/src/env/task/plugins/workflow-extractor-agent.ts +0 -225
- package/src/env/task/storage/index.ts +0 -6
- package/src/env/task/storage/sqlite-task-store.test.ts +0 -283
- package/src/env/task/storage/sqlite-task-store.ts +0 -903
- package/src/env/task/storage/task-search.test.ts +0 -291
- package/src/env/task/tag-service.test.ts +0 -198
- package/src/env/task/tag-service.ts +0 -264
- package/src/env/task/task-component.test.ts +0 -193
- package/src/env/task/task-component.ts +0 -658
- package/src/env/task/task-config-registration.test.ts +0 -57
- package/src/env/task/task-config-registration.ts +0 -37
- package/src/env/task/task-types.test.ts +0 -137
- package/src/env/task/tools/complete-tool.ts +0 -44
- package/src/env/task/tools/create-tool.ts +0 -49
- package/src/env/task/tools/delete-tool.ts +0 -43
- package/src/env/task/tools/get-tool.ts +0 -59
- package/src/env/task/tools/index.ts +0 -10
- package/src/env/task/tools/list-tool.ts +0 -40
- package/src/env/task/tools/operation/create-tool.ts +0 -48
- package/src/env/task/tools/operation/delete-tool.ts +0 -43
- package/src/env/task/tools/operation/get-tool.ts +0 -43
- package/src/env/task/tools/operation/index.ts +0 -9
- package/src/env/task/tools/operation/list-tool.ts +0 -40
- package/src/env/task/tools/operation/operation-tools.test.ts +0 -274
- package/src/env/task/tools/operation/operation-types.ts +0 -75
- package/src/env/task/tools/operation/update-tool.ts +0 -47
- package/src/env/task/tools/task-tools.test.ts +0 -203
- package/src/env/task/tools/task-types.test.ts +0 -75
- package/src/env/task/tools/task-types.ts +0 -68
- package/src/env/task/tools/update-tool.ts +0 -70
- package/src/env/task/types.ts +0 -160
- package/src/env/tool/built-in/bash.ts +0 -201
- package/src/env/tool/built-in/echo.ts +0 -29
- package/src/env/tool/built-in/edit-file.test.ts +0 -136
- package/src/env/tool/built-in/edit-file.ts +0 -92
- package/src/env/tool/built-in/glob.test.ts +0 -94
- package/src/env/tool/built-in/glob.ts +0 -65
- package/src/env/tool/built-in/grep.test.ts +0 -122
- package/src/env/tool/built-in/grep.ts +0 -108
- package/src/env/tool/built-in/index.ts +0 -44
- package/src/env/tool/built-in/read-file.test.ts +0 -84
- package/src/env/tool/built-in/read-file.ts +0 -75
- package/src/env/tool/built-in/write-file.test.ts +0 -119
- package/src/env/tool/built-in/write-file.ts +0 -68
- package/src/env/tool/index.ts +0 -24
- package/src/env/tool/registry.test.ts +0 -257
- package/src/env/tool/registry.ts +0 -167
- package/src/env/tool/tool-component.test.ts +0 -559
- package/src/env/tool/tool-component.ts +0 -563
- package/src/env/tool/tool-config-registration.test.ts +0 -249
- package/src/env/tool/tool-config-registration.ts +0 -46
- package/src/env/tool/types.ts +0 -267
- package/src/env/tool/validator.test.ts +0 -143
- package/src/env/tool/validator.ts +0 -44
- package/src/env/types.ts +0 -180
- package/src/env/workflow/ask-user-tool-registration.test.ts +0 -216
- package/src/env/workflow/complex-workflow.integration.test.ts +0 -1900
- package/src/env/workflow/decorators/decorator-node.ts +0 -229
- package/src/env/workflow/decorators/decorator.test.ts +0 -196
- package/src/env/workflow/decorators/edge.ts +0 -82
- package/src/env/workflow/decorators/index.ts +0 -31
- package/src/env/workflow/decorators/node-as.ts +0 -98
- package/src/env/workflow/decorators/workflow.ts +0 -54
- package/src/env/workflow/engine/dag-manager.test.ts +0 -570
- package/src/env/workflow/engine/dag-manager.ts +0 -594
- package/src/env/workflow/engine/engine.ts +0 -1422
- package/src/env/workflow/engine/event-bus.test.ts +0 -359
- package/src/env/workflow/engine/event-bus.ts +0 -156
- package/src/env/workflow/engine/executor-agent-session.test.ts +0 -84
- package/src/env/workflow/engine/executor.test.ts +0 -619
- package/src/env/workflow/engine/executor.ts +0 -593
- package/src/env/workflow/engine/index.ts +0 -24
- package/src/env/workflow/engine/node-registry.test.ts +0 -560
- package/src/env/workflow/engine/node-registry.ts +0 -289
- package/src/env/workflow/engine/resume-removed.test.ts +0 -22
- package/src/env/workflow/engine/scheduler.test.ts +0 -715
- package/src/env/workflow/engine/scheduler.ts +0 -318
- package/src/env/workflow/engine/workflow-engine.test.ts +0 -815
- package/src/env/workflow/extractor/workflow-converter.ts +0 -306
- package/src/env/workflow/fixtures.ts +0 -380
- package/src/env/workflow/index.ts +0 -38
- package/src/env/workflow/integration/run-resume-unified.test.ts +0 -186
- package/src/env/workflow/integration/service-integration.test.ts +0 -267
- package/src/env/workflow/metadata/keys.ts +0 -12
- package/src/env/workflow/nodes/agent-component-adapter.test.ts +0 -318
- package/src/env/workflow/nodes/agent-component-adapter.ts +0 -448
- package/src/env/workflow/nodes/agent-node.test.ts +0 -371
- package/src/env/workflow/nodes/agent-node.ts +0 -598
- package/src/env/workflow/nodes/ask-user-node.ts +0 -113
- package/src/env/workflow/nodes/condition-node.ts +0 -200
- package/src/env/workflow/nodes/index.ts +0 -9
- package/src/env/workflow/nodes/merge-node.ts +0 -141
- package/src/env/workflow/nodes/skill-node.test.ts +0 -253
- package/src/env/workflow/nodes/skill-node.ts +0 -393
- package/src/env/workflow/nodes/tool-node.test.ts +0 -251
- package/src/env/workflow/nodes/tool-node.ts +0 -493
- package/src/env/workflow/nodes/workflow-llm-history.test.ts +0 -455
- package/src/env/workflow/nodes/workflow-node.test.ts +0 -315
- package/src/env/workflow/nodes/workflow-node.ts +0 -311
- package/src/env/workflow/service/index.ts +0 -27
- package/src/env/workflow/service/registry.test.ts +0 -133
- package/src/env/workflow/service/registry.ts +0 -71
- package/src/env/workflow/service/workflow-service.test.ts +0 -310
- package/src/env/workflow/service/workflow-service.ts +0 -393
- package/src/env/workflow/storage/index.ts +0 -28
- package/src/env/workflow/storage/mock-repositories.ts +0 -385
- package/src/env/workflow/storage/sqlite.test.ts +0 -179
- package/src/env/workflow/storage/sqlite.ts +0 -163
- package/src/env/workflow/storage/workflow-repo.test.ts +0 -780
- package/src/env/workflow/storage/workflow-repo.ts +0 -342
- package/src/env/workflow/tools/ask-user-tool.ts +0 -82
- package/src/env/workflow/tools/index.ts +0 -26
- package/src/env/workflow/tools/run-workflow.test.ts +0 -352
- package/src/env/workflow/tools/run-workflow.ts +0 -214
- package/src/env/workflow/types/context.ts +0 -18
- package/src/env/workflow/types/decorators-types.ts +0 -198
- package/src/env/workflow/types/event.test.ts +0 -515
- package/src/env/workflow/types/event.ts +0 -193
- package/src/env/workflow/types/index.ts +0 -49
- package/src/env/workflow/types/run.test.ts +0 -437
- package/src/env/workflow/types/run.ts +0 -173
- package/src/env/workflow/types/workflow-hil.ts +0 -114
- package/src/env/workflow/types/workflow-message.test.ts +0 -138
- package/src/env/workflow/types/workflow-message.ts +0 -196
- package/src/env/workflow/types/workflow-session.test.ts +0 -95
- package/src/env/workflow/types/workflow-session.ts +0 -59
- package/src/env/workflow/types/workflow.test.ts +0 -495
- package/src/env/workflow/types/workflow.ts +0 -195
- package/src/env/workflow/types_compat.ts +0 -51
- package/src/env/workflow/utils/create-workflow.ts +0 -47
- package/src/env/workflow/utils/execution-state.ts +0 -245
- package/src/env/workflow/utils/index.ts +0 -18
- package/src/env/workflow/utils/node-registry-helper.ts +0 -58
- package/src/env/workflow/utils/recovery-validator.test.ts +0 -460
- package/src/env/workflow/utils/recovery-validator.ts +0 -377
- package/src/env/workflow/utils/session-parser.test.ts +0 -111
- package/src/env/workflow/utils/session-parser.ts +0 -94
- package/src/env/workflow/utils/session-recovery.test.ts +0 -334
- package/src/env/workflow/utils/session-recovery.ts +0 -188
- package/src/env/workflow/utils/template-resolver.test.ts +0 -258
- package/src/env/workflow/utils/template-resolver.ts +0 -436
- package/src/env/workflow/utils/validation-rules.ts +0 -149
- package/src/env/workflow/workflow-component.ts +0 -544
- package/src/index.ts +0 -422
- package/src/utils/id.ts +0 -21
|
@@ -1,570 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach } from 'vitest';
|
|
2
|
-
import { DAGManager, DAGAnalysis } from './dag-manager';
|
|
3
|
-
import type { WorkflowDefinition, NodeDefinition } from '../types';
|
|
4
|
-
|
|
5
|
-
// Helper to create a basic workflow definition
|
|
6
|
-
function createWorkflow(nodes: NodeDefinition[], name = 'test-workflow'): WorkflowDefinition {
|
|
7
|
-
return {
|
|
8
|
-
name,
|
|
9
|
-
version: '1.0',
|
|
10
|
-
nodes,
|
|
11
|
-
entry: '__default_entry__',
|
|
12
|
-
};
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
// Helper to create a node definition
|
|
16
|
-
function createNode(id: string, dependsOn: string[] = []): NodeDefinition {
|
|
17
|
-
return {
|
|
18
|
-
id,
|
|
19
|
-
type: 'test',
|
|
20
|
-
depends_on: dependsOn,
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
describe('DAGManager', () => {
|
|
25
|
-
describe('constructor', () => {
|
|
26
|
-
it('should create a DAGManager instance', () => {
|
|
27
|
-
const workflow = createWorkflow([createNode('A')]);
|
|
28
|
-
const manager = new DAGManager(workflow);
|
|
29
|
-
expect(manager).toBeInstanceOf(DAGManager);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it('should throw error for empty workflow', () => {
|
|
33
|
-
const workflow = createWorkflow([]);
|
|
34
|
-
expect(() => new DAGManager(workflow)).toThrow('At least one node is required');
|
|
35
|
-
});
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
describe('getExtendedDefinition()', () => {
|
|
39
|
-
it('should return extended definition with computed entry nodes', () => {
|
|
40
|
-
const workflow = createWorkflow([createNode('A'), createNode('B', ['A'])]);
|
|
41
|
-
const manager = new DAGManager(workflow);
|
|
42
|
-
const extended = manager.getExtendedDefinition();
|
|
43
|
-
|
|
44
|
-
expect(extended.computedEntry).toContain('A');
|
|
45
|
-
expect(extended.nodeMap.has('A')).toBe(true);
|
|
46
|
-
expect(extended.nodeMap.has('B')).toBe(true);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it('should compute entry nodes as nodes without dependencies', () => {
|
|
50
|
-
const workflow = createWorkflow([
|
|
51
|
-
createNode('A'),
|
|
52
|
-
createNode('B'),
|
|
53
|
-
createNode('C', ['A']),
|
|
54
|
-
]);
|
|
55
|
-
const manager = new DAGManager(workflow);
|
|
56
|
-
const extended = manager.getExtendedDefinition();
|
|
57
|
-
|
|
58
|
-
// A and B are entry nodes (no dependencies)
|
|
59
|
-
expect(extended.computedEntry).toHaveLength(2);
|
|
60
|
-
expect(extended.computedEntry).toContain('A');
|
|
61
|
-
expect(extended.computedEntry).toContain('B');
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it('should include topological order in extended definition', () => {
|
|
65
|
-
const workflow = createWorkflow([
|
|
66
|
-
createNode('A'),
|
|
67
|
-
createNode('B', ['A']),
|
|
68
|
-
createNode('C', ['B']),
|
|
69
|
-
]);
|
|
70
|
-
const manager = new DAGManager(workflow);
|
|
71
|
-
const extended = manager.getExtendedDefinition();
|
|
72
|
-
|
|
73
|
-
expect(extended.topologicalOrder).toHaveLength(3);
|
|
74
|
-
// A should come before B, B should come before C
|
|
75
|
-
const aIdx = extended.topologicalOrder.indexOf('A');
|
|
76
|
-
const bIdx = extended.topologicalOrder.indexOf('B');
|
|
77
|
-
const cIdx = extended.topologicalOrder.indexOf('C');
|
|
78
|
-
expect(aIdx).toBeLessThan(bIdx);
|
|
79
|
-
expect(bIdx).toBeLessThan(cIdx);
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
describe('analyze()', () => {
|
|
84
|
-
it('should analyze linear workflow correctly', () => {
|
|
85
|
-
const workflow = createWorkflow([
|
|
86
|
-
createNode('A'),
|
|
87
|
-
createNode('B', ['A']),
|
|
88
|
-
createNode('C', ['B']),
|
|
89
|
-
]);
|
|
90
|
-
const manager = new DAGManager(workflow);
|
|
91
|
-
const analysis = manager.analyze();
|
|
92
|
-
|
|
93
|
-
// Entry nodes: A (no dependencies)
|
|
94
|
-
expect(analysis.entryNodes).toEqual(['A']);
|
|
95
|
-
|
|
96
|
-
// Exit nodes: C (no dependents)
|
|
97
|
-
expect(analysis.exitNodes).toEqual(['C']);
|
|
98
|
-
|
|
99
|
-
// Levels: A at level 0, B at level 1, C at level 2
|
|
100
|
-
expect(analysis.levels).toHaveLength(3);
|
|
101
|
-
expect(analysis.levels[0]).toContain('A');
|
|
102
|
-
expect(analysis.levels[1]).toContain('B');
|
|
103
|
-
expect(analysis.levels[2]).toContain('C');
|
|
104
|
-
|
|
105
|
-
// Dependencies
|
|
106
|
-
expect(analysis.dependencies.get('A')).toEqual([]);
|
|
107
|
-
expect(analysis.dependencies.get('B')).toEqual(['A']);
|
|
108
|
-
expect(analysis.dependencies.get('C')).toEqual(['B']);
|
|
109
|
-
|
|
110
|
-
// Dependents
|
|
111
|
-
expect(analysis.dependents.get('A')).toContain('B');
|
|
112
|
-
expect(analysis.dependents.get('B')).toContain('C');
|
|
113
|
-
expect(analysis.dependents.get('C')).toEqual([]);
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
it('should analyze parallel workflow correctly', () => {
|
|
117
|
-
// A, B, C all start at the same time (no dependencies)
|
|
118
|
-
const workflow = createWorkflow([
|
|
119
|
-
createNode('A'),
|
|
120
|
-
createNode('B'),
|
|
121
|
-
createNode('C'),
|
|
122
|
-
]);
|
|
123
|
-
const manager = new DAGManager(workflow);
|
|
124
|
-
const analysis = manager.analyze();
|
|
125
|
-
|
|
126
|
-
// All are entry nodes
|
|
127
|
-
expect(analysis.entryNodes).toHaveLength(3);
|
|
128
|
-
|
|
129
|
-
// All are exit nodes (no dependents)
|
|
130
|
-
expect(analysis.exitNodes).toHaveLength(3);
|
|
131
|
-
|
|
132
|
-
// All at level 0 (can execute in parallel)
|
|
133
|
-
expect(analysis.levels).toHaveLength(1);
|
|
134
|
-
expect(analysis.levels[0]).toContain('A');
|
|
135
|
-
expect(analysis.levels[0]).toContain('B');
|
|
136
|
-
expect(analysis.levels[0]).toContain('C');
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
it('should analyze diamond workflow correctly', () => {
|
|
140
|
-
// Diamond: A -> B -> D, A -> C -> D
|
|
141
|
-
const workflow = createWorkflow([
|
|
142
|
-
createNode('A'),
|
|
143
|
-
createNode('B', ['A']),
|
|
144
|
-
createNode('C', ['A']),
|
|
145
|
-
createNode('D', ['B', 'C']),
|
|
146
|
-
]);
|
|
147
|
-
const manager = new DAGManager(workflow);
|
|
148
|
-
const analysis = manager.analyze();
|
|
149
|
-
|
|
150
|
-
// Entry: A
|
|
151
|
-
expect(analysis.entryNodes).toEqual(['A']);
|
|
152
|
-
|
|
153
|
-
// Exit: D
|
|
154
|
-
expect(analysis.exitNodes).toEqual(['D']);
|
|
155
|
-
|
|
156
|
-
// Levels: A at 0, B and C at 1, D at 2
|
|
157
|
-
expect(analysis.levels).toHaveLength(3);
|
|
158
|
-
expect(analysis.levels[0]).toContain('A');
|
|
159
|
-
expect(analysis.levels[1]).toContain('B');
|
|
160
|
-
expect(analysis.levels[1]).toContain('C');
|
|
161
|
-
expect(analysis.levels[2]).toContain('D');
|
|
162
|
-
|
|
163
|
-
// D depends on both B and C
|
|
164
|
-
expect(analysis.dependencies.get('D')).toEqual(['B', 'C']);
|
|
165
|
-
|
|
166
|
-
// B and C depend on A
|
|
167
|
-
expect(analysis.dependents.get('A')).toContain('B');
|
|
168
|
-
expect(analysis.dependents.get('A')).toContain('C');
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
it('should analyze complex workflow correctly', () => {
|
|
172
|
-
// Complex:
|
|
173
|
-
// A -> B -> D
|
|
174
|
-
// A -> C -> E
|
|
175
|
-
// B -> F
|
|
176
|
-
// C -> F
|
|
177
|
-
// D -> G
|
|
178
|
-
// E -> G
|
|
179
|
-
const workflow = createWorkflow([
|
|
180
|
-
createNode('A'),
|
|
181
|
-
createNode('B', ['A']),
|
|
182
|
-
createNode('C', ['A']),
|
|
183
|
-
createNode('D', ['B']),
|
|
184
|
-
createNode('E', ['C']),
|
|
185
|
-
createNode('F', ['B', 'C']),
|
|
186
|
-
createNode('G', ['D', 'E']),
|
|
187
|
-
]);
|
|
188
|
-
const manager = new DAGManager(workflow);
|
|
189
|
-
const analysis = manager.analyze();
|
|
190
|
-
|
|
191
|
-
// Entry: A
|
|
192
|
-
expect(analysis.entryNodes).toEqual(['A']);
|
|
193
|
-
|
|
194
|
-
// Exit: F, G
|
|
195
|
-
expect(analysis.exitNodes).toContain('F');
|
|
196
|
-
expect(analysis.exitNodes).toContain('G');
|
|
197
|
-
|
|
198
|
-
// Levels should be computed
|
|
199
|
-
expect(analysis.levels[0]).toContain('A');
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
it('should identify critical path', () => {
|
|
203
|
-
const workflow = createWorkflow([
|
|
204
|
-
createNode('A'),
|
|
205
|
-
createNode('B', ['A']),
|
|
206
|
-
createNode('C', ['B']),
|
|
207
|
-
]);
|
|
208
|
-
const manager = new DAGManager(workflow);
|
|
209
|
-
const analysis = manager.analyze();
|
|
210
|
-
|
|
211
|
-
expect(analysis.criticalPath).toBeDefined();
|
|
212
|
-
expect(analysis.criticalPath.length).toBeGreaterThan(0);
|
|
213
|
-
});
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
describe('getTopologicalOrder()', () => {
|
|
217
|
-
it('should return nodes in topological order for linear workflow', () => {
|
|
218
|
-
const workflow = createWorkflow([
|
|
219
|
-
createNode('A'),
|
|
220
|
-
createNode('B', ['A']),
|
|
221
|
-
createNode('C', ['B']),
|
|
222
|
-
]);
|
|
223
|
-
const manager = new DAGManager(workflow);
|
|
224
|
-
const order = manager.getTopologicalOrder();
|
|
225
|
-
|
|
226
|
-
expect(order).toHaveLength(3);
|
|
227
|
-
const aIdx = order.indexOf('A');
|
|
228
|
-
const bIdx = order.indexOf('B');
|
|
229
|
-
const cIdx = order.indexOf('C');
|
|
230
|
-
expect(aIdx).toBeLessThan(bIdx);
|
|
231
|
-
expect(bIdx).toBeLessThan(cIdx);
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
it('should handle parallel nodes in topological order', () => {
|
|
235
|
-
const workflow = createWorkflow([
|
|
236
|
-
createNode('A'),
|
|
237
|
-
createNode('B'),
|
|
238
|
-
createNode('C'),
|
|
239
|
-
]);
|
|
240
|
-
const manager = new DAGManager(workflow);
|
|
241
|
-
const order = manager.getTopologicalOrder();
|
|
242
|
-
|
|
243
|
-
expect(order).toHaveLength(3);
|
|
244
|
-
expect(order).toContain('A');
|
|
245
|
-
expect(order).toContain('B');
|
|
246
|
-
expect(order).toContain('C');
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
it('should handle diamond shape in topological order', () => {
|
|
250
|
-
const workflow = createWorkflow([
|
|
251
|
-
createNode('A'),
|
|
252
|
-
createNode('B', ['A']),
|
|
253
|
-
createNode('C', ['A']),
|
|
254
|
-
createNode('D', ['B', 'C']),
|
|
255
|
-
]);
|
|
256
|
-
const manager = new DAGManager(workflow);
|
|
257
|
-
const order = manager.getTopologicalOrder();
|
|
258
|
-
|
|
259
|
-
expect(order).toHaveLength(4);
|
|
260
|
-
const aIdx = order.indexOf('A');
|
|
261
|
-
const bIdx = order.indexOf('B');
|
|
262
|
-
const cIdx = order.indexOf('C');
|
|
263
|
-
const dIdx = order.indexOf('D');
|
|
264
|
-
|
|
265
|
-
// A should be before B, C
|
|
266
|
-
expect(aIdx).toBeLessThan(bIdx);
|
|
267
|
-
expect(aIdx).toBeLessThan(cIdx);
|
|
268
|
-
// B and C should be before D
|
|
269
|
-
expect(bIdx).toBeLessThan(dIdx);
|
|
270
|
-
expect(cIdx).toBeLessThan(dIdx);
|
|
271
|
-
});
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
describe('getReadyNodes()', () => {
|
|
275
|
-
it('should return entry nodes when nothing is completed', () => {
|
|
276
|
-
const workflow = createWorkflow([
|
|
277
|
-
createNode('A'),
|
|
278
|
-
createNode('B', ['A']),
|
|
279
|
-
createNode('C', ['B']),
|
|
280
|
-
]);
|
|
281
|
-
const manager = new DAGManager(workflow);
|
|
282
|
-
const ready = manager.getReadyNodes(new Set());
|
|
283
|
-
|
|
284
|
-
expect(ready).toEqual(['A']);
|
|
285
|
-
});
|
|
286
|
-
|
|
287
|
-
it('should return next nodes when dependencies are met', () => {
|
|
288
|
-
const workflow = createWorkflow([
|
|
289
|
-
createNode('A'),
|
|
290
|
-
createNode('B', ['A']),
|
|
291
|
-
createNode('C', ['B']),
|
|
292
|
-
]);
|
|
293
|
-
const manager = new DAGManager(workflow);
|
|
294
|
-
const ready = manager.getReadyNodes(new Set(['A']));
|
|
295
|
-
|
|
296
|
-
expect(ready).toEqual(['B']);
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
it('should return multiple nodes when parallel dependencies are met', () => {
|
|
300
|
-
// Diamond: A -> B -> D, A -> C -> D
|
|
301
|
-
const workflow = createWorkflow([
|
|
302
|
-
createNode('A'),
|
|
303
|
-
createNode('B', ['A']),
|
|
304
|
-
createNode('C', ['A']),
|
|
305
|
-
createNode('D', ['B', 'C']),
|
|
306
|
-
]);
|
|
307
|
-
const manager = new DAGManager(workflow);
|
|
308
|
-
|
|
309
|
-
// After A is done, B and C should be ready
|
|
310
|
-
const readyAfterA = manager.getReadyNodes(new Set(['A']));
|
|
311
|
-
expect(readyAfterA).toContain('B');
|
|
312
|
-
expect(readyAfterA).toContain('C');
|
|
313
|
-
|
|
314
|
-
// After B and C are done, D should be ready
|
|
315
|
-
const readyAfterBC = manager.getReadyNodes(new Set(['A', 'B', 'C']));
|
|
316
|
-
expect(readyAfterBC).toEqual(['D']);
|
|
317
|
-
});
|
|
318
|
-
|
|
319
|
-
it('should return empty array when workflow is complete', () => {
|
|
320
|
-
const workflow = createWorkflow([
|
|
321
|
-
createNode('A'),
|
|
322
|
-
createNode('B', ['A']),
|
|
323
|
-
]);
|
|
324
|
-
const manager = new DAGManager(workflow);
|
|
325
|
-
const ready = manager.getReadyNodes(new Set(['A', 'B']));
|
|
326
|
-
|
|
327
|
-
expect(ready).toEqual([]);
|
|
328
|
-
});
|
|
329
|
-
|
|
330
|
-
it('should return all ready nodes for parallel workflow', () => {
|
|
331
|
-
const workflow = createWorkflow([
|
|
332
|
-
createNode('A'),
|
|
333
|
-
createNode('B'),
|
|
334
|
-
createNode('C'),
|
|
335
|
-
]);
|
|
336
|
-
const manager = new DAGManager(workflow);
|
|
337
|
-
const ready = manager.getReadyNodes(new Set());
|
|
338
|
-
|
|
339
|
-
expect(ready).toHaveLength(3);
|
|
340
|
-
expect(ready).toContain('A');
|
|
341
|
-
expect(ready).toContain('B');
|
|
342
|
-
expect(ready).toContain('C');
|
|
343
|
-
});
|
|
344
|
-
});
|
|
345
|
-
|
|
346
|
-
describe('areDependenciesMet()', () => {
|
|
347
|
-
it('should return true when node has no dependencies', () => {
|
|
348
|
-
const workflow = createWorkflow([createNode('A')]);
|
|
349
|
-
const manager = new DAGManager(workflow);
|
|
350
|
-
|
|
351
|
-
expect(manager.areDependenciesMet('A', new Set())).toBe(true);
|
|
352
|
-
});
|
|
353
|
-
|
|
354
|
-
it('should return true when all dependencies are completed', () => {
|
|
355
|
-
const workflow = createWorkflow([
|
|
356
|
-
createNode('A'),
|
|
357
|
-
createNode('B', ['A']),
|
|
358
|
-
]);
|
|
359
|
-
const manager = new DAGManager(workflow);
|
|
360
|
-
|
|
361
|
-
expect(manager.areDependenciesMet('B', new Set(['A']))).toBe(true);
|
|
362
|
-
});
|
|
363
|
-
|
|
364
|
-
it('should return false when some dependencies are not completed', () => {
|
|
365
|
-
const workflow = createWorkflow([
|
|
366
|
-
createNode('A'),
|
|
367
|
-
createNode('B', ['A']),
|
|
368
|
-
createNode('C', ['A']),
|
|
369
|
-
]);
|
|
370
|
-
const manager = new DAGManager(workflow);
|
|
371
|
-
|
|
372
|
-
expect(manager.areDependenciesMet('C', new Set(['B']))).toBe(false);
|
|
373
|
-
});
|
|
374
|
-
|
|
375
|
-
it('should handle multiple dependencies', () => {
|
|
376
|
-
const workflow = createWorkflow([
|
|
377
|
-
createNode('A'),
|
|
378
|
-
createNode('B', ['A']),
|
|
379
|
-
createNode('C', ['A']),
|
|
380
|
-
createNode('D', ['B', 'C']),
|
|
381
|
-
]);
|
|
382
|
-
const manager = new DAGManager(workflow);
|
|
383
|
-
|
|
384
|
-
expect(manager.areDependenciesMet('D', new Set(['A', 'B']))).toBe(false);
|
|
385
|
-
expect(manager.areDependenciesMet('D', new Set(['A', 'B', 'C']))).toBe(true);
|
|
386
|
-
});
|
|
387
|
-
});
|
|
388
|
-
|
|
389
|
-
describe('isCyclic()', () => {
|
|
390
|
-
it('should return false for linear workflow', () => {
|
|
391
|
-
const workflow = createWorkflow([
|
|
392
|
-
createNode('A'),
|
|
393
|
-
createNode('B', ['A']),
|
|
394
|
-
createNode('C', ['B']),
|
|
395
|
-
]);
|
|
396
|
-
const manager = new DAGManager(workflow);
|
|
397
|
-
|
|
398
|
-
expect(manager.isCyclic()).toBe(false);
|
|
399
|
-
});
|
|
400
|
-
|
|
401
|
-
it('should return false for diamond workflow', () => {
|
|
402
|
-
const workflow = createWorkflow([
|
|
403
|
-
createNode('A'),
|
|
404
|
-
createNode('B', ['A']),
|
|
405
|
-
createNode('C', ['A']),
|
|
406
|
-
createNode('D', ['B', 'C']),
|
|
407
|
-
]);
|
|
408
|
-
const manager = new DAGManager(workflow);
|
|
409
|
-
|
|
410
|
-
expect(manager.isCyclic()).toBe(false);
|
|
411
|
-
});
|
|
412
|
-
|
|
413
|
-
it('should return true when cycle exists (A -> B -> C -> A)', () => {
|
|
414
|
-
const workflow = createWorkflow([
|
|
415
|
-
createNode('A'),
|
|
416
|
-
createNode('B', ['A']),
|
|
417
|
-
createNode('C', ['B']),
|
|
418
|
-
// Add a dependency that creates a cycle (C -> A)
|
|
419
|
-
], 'cycle-workflow');
|
|
420
|
-
|
|
421
|
-
// Create a custom workflow with cycle for testing
|
|
422
|
-
const cycleWorkflow: WorkflowDefinition = {
|
|
423
|
-
name: 'cycle-workflow',
|
|
424
|
-
version: '1.0',
|
|
425
|
-
nodes: [
|
|
426
|
-
{ id: 'A', type: 'test', depends_on: ['C'] }, // C -> A
|
|
427
|
-
{ id: 'B', type: 'test', depends_on: ['A'] }, // A -> B
|
|
428
|
-
{ id: 'C', type: 'test', depends_on: ['B'] }, // B -> C
|
|
429
|
-
],
|
|
430
|
-
};
|
|
431
|
-
const manager = new DAGManager(cycleWorkflow);
|
|
432
|
-
|
|
433
|
-
expect(manager.isCyclic()).toBe(true);
|
|
434
|
-
});
|
|
435
|
-
|
|
436
|
-
it('should return true for self-referencing node', () => {
|
|
437
|
-
const workflow: WorkflowDefinition = {
|
|
438
|
-
name: 'self-ref',
|
|
439
|
-
version: '1.0',
|
|
440
|
-
nodes: [
|
|
441
|
-
{ id: 'A', type: 'test', depends_on: ['A'] },
|
|
442
|
-
],
|
|
443
|
-
};
|
|
444
|
-
const manager = new DAGManager(workflow);
|
|
445
|
-
|
|
446
|
-
expect(manager.isCyclic()).toBe(true);
|
|
447
|
-
});
|
|
448
|
-
});
|
|
449
|
-
|
|
450
|
-
describe('validate()', () => {
|
|
451
|
-
it('should return valid for correct workflow', () => {
|
|
452
|
-
const workflow = createWorkflow([
|
|
453
|
-
createNode('A'),
|
|
454
|
-
createNode('B', ['A']),
|
|
455
|
-
createNode('C', ['B']),
|
|
456
|
-
]);
|
|
457
|
-
const manager = new DAGManager(workflow);
|
|
458
|
-
const result = manager.validate();
|
|
459
|
-
|
|
460
|
-
expect(result.valid).toBe(true);
|
|
461
|
-
expect(result.errors).toHaveLength(0);
|
|
462
|
-
});
|
|
463
|
-
|
|
464
|
-
it('should detect missing dependency reference', () => {
|
|
465
|
-
const workflow: WorkflowDefinition = {
|
|
466
|
-
name: 'invalid',
|
|
467
|
-
version: '1.0',
|
|
468
|
-
nodes: [
|
|
469
|
-
{ id: 'A', type: 'test' },
|
|
470
|
-
{ id: 'B', type: 'test', depends_on: ['nonexistent'] },
|
|
471
|
-
],
|
|
472
|
-
};
|
|
473
|
-
const manager = new DAGManager(workflow);
|
|
474
|
-
const result = manager.validate();
|
|
475
|
-
|
|
476
|
-
expect(result.valid).toBe(false);
|
|
477
|
-
expect(result.errors.some(e => e.includes('nonexistent'))).toBe(true);
|
|
478
|
-
});
|
|
479
|
-
|
|
480
|
-
it('should detect cycle in workflow', () => {
|
|
481
|
-
const workflow: WorkflowDefinition = {
|
|
482
|
-
name: 'cycle',
|
|
483
|
-
version: '1.0',
|
|
484
|
-
nodes: [
|
|
485
|
-
{ id: 'A', type: 'test', depends_on: ['C'] },
|
|
486
|
-
{ id: 'B', type: 'test', depends_on: ['A'] },
|
|
487
|
-
{ id: 'C', type: 'test', depends_on: ['B'] },
|
|
488
|
-
],
|
|
489
|
-
};
|
|
490
|
-
const manager = new DAGManager(workflow);
|
|
491
|
-
const result = manager.validate();
|
|
492
|
-
|
|
493
|
-
expect(result.valid).toBe(false);
|
|
494
|
-
expect(result.errors.some(e => e.toLowerCase().includes('cycle'))).toBe(true);
|
|
495
|
-
});
|
|
496
|
-
|
|
497
|
-
it('should detect duplicate node IDs', () => {
|
|
498
|
-
const workflow: WorkflowDefinition = {
|
|
499
|
-
name: 'duplicate',
|
|
500
|
-
version: '1.0',
|
|
501
|
-
nodes: [
|
|
502
|
-
{ id: 'A', type: 'test' },
|
|
503
|
-
{ id: 'A', type: 'test' }, // duplicate
|
|
504
|
-
],
|
|
505
|
-
};
|
|
506
|
-
// Constructor should throw for duplicate IDs
|
|
507
|
-
expect(() => new DAGManager(workflow)).toThrow('Duplicate node ID');
|
|
508
|
-
});
|
|
509
|
-
|
|
510
|
-
it('should detect empty node ID', () => {
|
|
511
|
-
const workflow: WorkflowDefinition = {
|
|
512
|
-
name: 'empty-id',
|
|
513
|
-
version: '1.0',
|
|
514
|
-
nodes: [
|
|
515
|
-
{ id: '', type: 'test' },
|
|
516
|
-
],
|
|
517
|
-
};
|
|
518
|
-
|
|
519
|
-
// Constructor should throw for empty node ID
|
|
520
|
-
expect(() => new DAGManager(workflow)).toThrow('Node ID cannot be empty');
|
|
521
|
-
});
|
|
522
|
-
});
|
|
523
|
-
|
|
524
|
-
describe('edge cases', () => {
|
|
525
|
-
it('should handle single node workflow', () => {
|
|
526
|
-
const workflow = createWorkflow([createNode('A')]);
|
|
527
|
-
const manager = new DAGManager(workflow);
|
|
528
|
-
|
|
529
|
-
expect(manager.analyze().entryNodes).toEqual(['A']);
|
|
530
|
-
expect(manager.analyze().exitNodes).toEqual(['A']);
|
|
531
|
-
expect(manager.analyze().levels).toHaveLength(1);
|
|
532
|
-
expect(manager.getTopologicalOrder()).toEqual(['A']);
|
|
533
|
-
expect(manager.getReadyNodes(new Set())).toEqual(['A']);
|
|
534
|
-
expect(manager.getReadyNodes(new Set(['A']))).toEqual([]);
|
|
535
|
-
});
|
|
536
|
-
|
|
537
|
-
it('should handle workflow with multiple entry nodes', () => {
|
|
538
|
-
const workflow = createWorkflow([
|
|
539
|
-
createNode('A'),
|
|
540
|
-
createNode('B'),
|
|
541
|
-
createNode('C', ['A', 'B']),
|
|
542
|
-
]);
|
|
543
|
-
const manager = new DAGManager(workflow);
|
|
544
|
-
const analysis = manager.analyze();
|
|
545
|
-
|
|
546
|
-
expect(analysis.entryNodes).toContain('A');
|
|
547
|
-
expect(analysis.entryNodes).toContain('B');
|
|
548
|
-
expect(analysis.exitNodes).toContain('C');
|
|
549
|
-
});
|
|
550
|
-
|
|
551
|
-
it('should handle nodes with many dependencies', () => {
|
|
552
|
-
const workflow = createWorkflow([
|
|
553
|
-
createNode('A'),
|
|
554
|
-
createNode('B'),
|
|
555
|
-
createNode('C'),
|
|
556
|
-
createNode('D'),
|
|
557
|
-
createNode('E', ['A', 'B', 'C', 'D']),
|
|
558
|
-
]);
|
|
559
|
-
const manager = new DAGManager(workflow);
|
|
560
|
-
const analysis = manager.analyze();
|
|
561
|
-
|
|
562
|
-
expect(analysis.dependencies.get('E')).toEqual(['A', 'B', 'C', 'D']);
|
|
563
|
-
expect(analysis.levels[0]).toContain('A');
|
|
564
|
-
expect(analysis.levels[0]).toContain('B');
|
|
565
|
-
expect(analysis.levels[0]).toContain('C');
|
|
566
|
-
expect(analysis.levels[0]).toContain('D');
|
|
567
|
-
expect(analysis.levels[1]).toContain('E');
|
|
568
|
-
});
|
|
569
|
-
});
|
|
570
|
-
});
|