taskmeld 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +18 -0
- package/README.md +172 -0
- package/README.zh-CN.md +172 -0
- package/dist/src/app/app-context-env.js +51 -0
- package/dist/src/app/create-app-context.js +127 -0
- package/dist/src/app/data-dir.js +29 -0
- package/dist/src/app/pipeline-config.js +105 -0
- package/dist/src/app/pipeline-plugin-config.js +2 -0
- package/dist/src/app/pipeline-registry.js +502 -0
- package/dist/src/app/pipeline-runtime.js +202 -0
- package/dist/src/app/runtime-store.js +151 -0
- package/dist/src/app/user-config.js +37 -0
- package/dist/src/artifacts/artifact-cleanup.js +192 -0
- package/dist/src/artifacts/artifact-index.js +262 -0
- package/dist/src/artifacts/artifact-rebuilder.js +120 -0
- package/dist/src/artifacts/storage-service.js +371 -0
- package/dist/src/cli/bootstrap.js +226 -0
- package/dist/src/cli/commands/agent.js +126 -0
- package/dist/src/cli/commands/artifact.js +175 -0
- package/dist/src/cli/commands/init.js +150 -0
- package/dist/src/cli/commands/pipeline/errors.js +37 -0
- package/dist/src/cli/commands/pipeline/result.js +179 -0
- package/dist/src/cli/commands/pipeline/selector.js +51 -0
- package/dist/src/cli/commands/pipeline/types.js +2 -0
- package/dist/src/cli/commands/pipeline/watch.js +67 -0
- package/dist/src/cli/commands/pipeline.js +339 -0
- package/dist/src/cli/commands/scheduler.js +81 -0
- package/dist/src/cli/commands/server.js +70 -0
- package/dist/src/cli/commands/system.js +21 -0
- package/dist/src/cli/errors.js +71 -0
- package/dist/src/cli/help.js +184 -0
- package/dist/src/cli/index.js +65 -0
- package/dist/src/cli/output.js +19 -0
- package/dist/src/cli/renderers/engine/json.js +67 -0
- package/dist/src/cli/renderers/engine/markdown.js +95 -0
- package/dist/src/cli/renderers/engine/types.js +2 -0
- package/dist/src/cli/renderers/engine/utils.js +32 -0
- package/dist/src/cli/renderers/index.js +27 -0
- package/dist/src/cli/renderers/specs/agent.js +78 -0
- package/dist/src/cli/renderers/specs/artifact.js +32 -0
- package/dist/src/cli/renderers/specs/index.js +36 -0
- package/dist/src/cli/renderers/specs/init.js +25 -0
- package/dist/src/cli/renderers/specs/pipeline.js +561 -0
- package/dist/src/cli/renderers/specs/scheduler.js +46 -0
- package/dist/src/cli/renderers/specs/server.js +38 -0
- package/dist/src/cli/renderers/specs/system.js +36 -0
- package/dist/src/cli/router.js +199 -0
- package/dist/src/cli/server-runtime-client.js +780 -0
- package/dist/src/cli/types.js +2 -0
- package/dist/src/gateway/frame-sanitizer.js +78 -0
- package/dist/src/gateway/gateway-client.js +462 -0
- package/dist/src/gateway/index.js +18 -0
- package/dist/src/gateway/types.js +2 -0
- package/dist/src/index.js +123 -0
- package/dist/src/logs/run-log-reader.js +141 -0
- package/dist/src/logs/run-log-service.js +42 -0
- package/dist/src/logs/run-log-types.js +2 -0
- package/dist/src/pipeline/agent-activity.js +191 -0
- package/dist/src/pipeline/artifact-storage.js +208 -0
- package/dist/src/pipeline/diagnostics/dependency-diagnostic.js +105 -0
- package/dist/src/pipeline/diagnostics/index.js +6 -0
- package/dist/src/pipeline/dispatch/pipeline-inbound-queue.js +215 -0
- package/dist/src/pipeline/dispatch/pipeline-link-dispatcher.js +66 -0
- package/dist/src/pipeline/dispatch/pipeline-link-store.js +94 -0
- package/dist/src/pipeline/dispatch/pipeline-queue-drainer.js +71 -0
- package/dist/src/pipeline/execution/dependency-check.js +52 -0
- package/dist/src/pipeline/execution/execution-result.js +2 -0
- package/dist/src/pipeline/execution/group-item-executor.js +128 -0
- package/dist/src/pipeline/execution/index.js +5 -0
- package/dist/src/pipeline/execution/node-item-executor.js +58 -0
- package/dist/src/pipeline/execution/node-runner.js +159 -0
- package/dist/src/pipeline/execution/readiness-state.js +10 -0
- package/dist/src/pipeline/execution/reject-handler.js +94 -0
- package/dist/src/pipeline/execution/rejected-artifact-archiver.js +45 -0
- package/dist/src/pipeline/execution/route-item-manager.js +253 -0
- package/dist/src/pipeline/execution/run-abort-controller.js +66 -0
- package/dist/src/pipeline/execution/run-state-helpers.js +257 -0
- package/dist/src/pipeline/execution/service.js +165 -0
- package/dist/src/pipeline/execution/session-registry.js +96 -0
- package/dist/src/pipeline/execution/structured-node-runner.js +411 -0
- package/dist/src/pipeline/execution-status.js +96 -0
- package/dist/src/pipeline/execution-timeout.js +21 -0
- package/dist/src/pipeline/identity/index.js +32 -0
- package/dist/src/pipeline/identity/types.js +2 -0
- package/dist/src/pipeline/item-batch-controller.js +227 -0
- package/dist/src/pipeline/output/pipeline-output-resolver.js +91 -0
- package/dist/src/pipeline/output/pipeline-output-store.js +60 -0
- package/dist/src/pipeline/runtime-model.js +173 -0
- package/dist/src/pipeline/scheduler/dependency-state.js +144 -0
- package/dist/src/pipeline/scheduler-service.js +314 -0
- package/dist/src/pipeline/state/group-item-state.js +50 -0
- package/dist/src/pipeline/state/group-run-state.js +41 -0
- package/dist/src/pipeline/state/index.js +20 -0
- package/dist/src/pipeline/state/node-item-state.js +67 -0
- package/dist/src/pipeline/state/node-run-state.js +51 -0
- package/dist/src/pipeline/state/types.js +2 -0
- package/dist/src/pipeline/state-machine.js +101 -0
- package/dist/src/pipeline/structured-output/contract.js +133 -0
- package/dist/src/pipeline/structured-output/index.js +22 -0
- package/dist/src/pipeline/structured-output/parser.js +214 -0
- package/dist/src/pipeline/structured-output/prompt.js +290 -0
- package/dist/src/pipeline/structured-output/waiter.js +139 -0
- package/dist/src/pipeline/template.js +135 -0
- package/dist/src/pipeline/timeline-log-store.js +57 -0
- package/dist/src/pipeline/tool-activity.js +94 -0
- package/dist/src/pipeline/types/pipeline-link.js +7 -0
- package/dist/src/pipeline/types/pipeline-output.js +11 -0
- package/dist/src/pipeline/types/workflow.js +2 -0
- package/dist/src/pipeline/workflow/branch-rules.js +74 -0
- package/dist/src/pipeline/workflow/defaults.js +48 -0
- package/dist/src/pipeline/workflow/io.js +89 -0
- package/dist/src/pipeline/workflow/normalize.js +347 -0
- package/dist/src/pipeline/workflow/routes.js +16 -0
- package/dist/src/pipeline/workflow/template-mapper.js +113 -0
- package/dist/src/pipeline/workflow/validate.js +312 -0
- package/dist/src/pipeline/workflow-graph.js +165 -0
- package/dist/src/server/api-handler.js +163 -0
- package/dist/src/server/http-utils.js +34 -0
- package/dist/src/server/middleware.js +61 -0
- package/dist/src/server/router.js +105 -0
- package/dist/src/server/routes/agents.js +189 -0
- package/dist/src/server/routes/artifacts.js +163 -0
- package/dist/src/server/routes/gateway.js +18 -0
- package/dist/src/server/routes/health.js +16 -0
- package/dist/src/server/routes/logs.js +73 -0
- package/dist/src/server/routes/pipeline-batch.js +163 -0
- package/dist/src/server/routes/pipeline-diagnostics.js +33 -0
- package/dist/src/server/routes/pipeline-identity.js +24 -0
- package/dist/src/server/routes/pipeline-links.js +117 -0
- package/dist/src/server/routes/pipeline-outputs.js +27 -0
- package/dist/src/server/routes/pipeline-queue.js +62 -0
- package/dist/src/server/routes/pipeline-runtime.js +162 -0
- package/dist/src/server/routes/pipeline-scheduler.js +69 -0
- package/dist/src/server/routes/pipeline-workflow.js +180 -0
- package/dist/src/server/routes/pipelines.js +96 -0
- package/dist/src/server/routes/sessions.js +244 -0
- package/dist/src/server/routes/timeline.js +14 -0
- package/dist/src/server/serve-static.js +42 -0
- package/dist/src/server/types.js +2 -0
- package/dist/src/services/agent-service.js +79 -0
- package/dist/src/services/artifact-service.js +74 -0
- package/dist/src/services/gateway-read-helpers.js +10 -0
- package/dist/src/services/index.js +23 -0
- package/dist/src/services/pipeline-service.js +529 -0
- package/dist/src/services/pipeline-status.js +93 -0
- package/dist/src/services/read-services.js +60 -0
- package/dist/src/services/scheduler-service.js +37 -0
- package/dist/src/services/session-service.js +227 -0
- package/dist/src/services/system-service.js +26 -0
- package/dist/src/transport/ws-broker.js +48 -0
- package/dist/src/utils/array.js +17 -0
- package/dist/src/utils/guards.js +5 -0
- package/dist/src/utils/session.js +60 -0
- package/dist/src/version.js +5 -0
- package/package.json +61 -0
- package/web/dist/assets/index-CWnfhkn-.js +65 -0
- package/web/dist/assets/index-gZ0xOfSO.css +1 -0
- package/web/dist/assets/jetbrains-mono-cyrillic-400-normal-BEIGL1Tu.woff2 +0 -0
- package/web/dist/assets/jetbrains-mono-cyrillic-400-normal-ugxPyKxw.woff +0 -0
- package/web/dist/assets/jetbrains-mono-cyrillic-500-normal-DJqRU3vO.woff +0 -0
- package/web/dist/assets/jetbrains-mono-cyrillic-500-normal-DmUKJPL_.woff2 +0 -0
- package/web/dist/assets/jetbrains-mono-cyrillic-700-normal-BWTpRfYl.woff2 +0 -0
- package/web/dist/assets/jetbrains-mono-cyrillic-700-normal-CEoEElIJ.woff +0 -0
- package/web/dist/assets/jetbrains-mono-greek-400-normal-B9oWc5Lo.woff +0 -0
- package/web/dist/assets/jetbrains-mono-greek-400-normal-C190GLew.woff2 +0 -0
- package/web/dist/assets/jetbrains-mono-greek-500-normal-D7SFKleX.woff +0 -0
- package/web/dist/assets/jetbrains-mono-greek-500-normal-JpySY46c.woff2 +0 -0
- package/web/dist/assets/jetbrains-mono-greek-700-normal-C6CZE3T8.woff2 +0 -0
- package/web/dist/assets/jetbrains-mono-greek-700-normal-DEigVDxa.woff +0 -0
- package/web/dist/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff +0 -0
- package/web/dist/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
- package/web/dist/assets/jetbrains-mono-latin-500-normal-BWZEU5yA.woff2 +0 -0
- package/web/dist/assets/jetbrains-mono-latin-500-normal-CJOVTJB7.woff +0 -0
- package/web/dist/assets/jetbrains-mono-latin-700-normal-BYuf6tUa.woff2 +0 -0
- package/web/dist/assets/jetbrains-mono-latin-700-normal-D3wTyLJW.woff +0 -0
- package/web/dist/assets/jetbrains-mono-latin-ext-400-normal-Bc8Ftmh3.woff2 +0 -0
- package/web/dist/assets/jetbrains-mono-latin-ext-400-normal-fXTG6kC5.woff +0 -0
- package/web/dist/assets/jetbrains-mono-latin-ext-500-normal-Cut-4mMH.woff2 +0 -0
- package/web/dist/assets/jetbrains-mono-latin-ext-500-normal-ckzbgY84.woff +0 -0
- package/web/dist/assets/jetbrains-mono-latin-ext-700-normal-CZipNAKV.woff2 +0 -0
- package/web/dist/assets/jetbrains-mono-latin-ext-700-normal-CxPITLHs.woff +0 -0
- package/web/dist/assets/jetbrains-mono-vietnamese-400-normal-CqNFfHCs.woff +0 -0
- package/web/dist/assets/jetbrains-mono-vietnamese-500-normal-DNRqzVM1.woff +0 -0
- package/web/dist/assets/jetbrains-mono-vietnamese-700-normal-BDLVIk2r.woff +0 -0
- package/web/dist/assets/space-grotesk-latin-400-normal-BnQMeOim.woff +0 -0
- package/web/dist/assets/space-grotesk-latin-400-normal-CJ-V5oYT.woff2 +0 -0
- package/web/dist/assets/space-grotesk-latin-500-normal-CNSSEhBt.woff +0 -0
- package/web/dist/assets/space-grotesk-latin-500-normal-lFbtlQH6.woff2 +0 -0
- package/web/dist/assets/space-grotesk-latin-700-normal-CwsQ-cCU.woff +0 -0
- package/web/dist/assets/space-grotesk-latin-700-normal-RjhwGPKo.woff2 +0 -0
- package/web/dist/assets/space-grotesk-latin-ext-400-normal-CfP_5XZW.woff2 +0 -0
- package/web/dist/assets/space-grotesk-latin-ext-400-normal-DRPE3kg4.woff +0 -0
- package/web/dist/assets/space-grotesk-latin-ext-500-normal-3dgZTiw9.woff +0 -0
- package/web/dist/assets/space-grotesk-latin-ext-500-normal-DUe3BAxM.woff2 +0 -0
- package/web/dist/assets/space-grotesk-latin-ext-700-normal-BQnZhY3m.woff2 +0 -0
- package/web/dist/assets/space-grotesk-latin-ext-700-normal-HVCqSBdx.woff +0 -0
- package/web/dist/assets/space-grotesk-vietnamese-400-normal-B7xT_GF5.woff2 +0 -0
- package/web/dist/assets/space-grotesk-vietnamese-400-normal-BIWiOVfw.woff +0 -0
- package/web/dist/assets/space-grotesk-vietnamese-500-normal-BTqKIpxg.woff +0 -0
- package/web/dist/assets/space-grotesk-vietnamese-500-normal-BmEvtly_.woff2 +0 -0
- package/web/dist/assets/space-grotesk-vietnamese-700-normal-DMty7AZE.woff2 +0 -0
- package/web/dist/assets/space-grotesk-vietnamese-700-normal-Duxec5Rn.woff +0 -0
- package/web/dist/favicon.svg +10 -0
- package/web/dist/index.html +14 -0
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createRouteItemManager = void 0;
|
|
4
|
+
const node_crypto_1 = require("node:crypto");
|
|
5
|
+
const readiness_state_1 = require("./readiness-state");
|
|
6
|
+
const state_machine_1 = require("../state-machine");
|
|
7
|
+
const identity_1 = require("../identity");
|
|
8
|
+
const routes_1 = require("../workflow/routes");
|
|
9
|
+
const state_1 = require("../state");
|
|
10
|
+
const ctx = (reason, extra) => ({ reason, ...extra });
|
|
11
|
+
const normalizeAllowedRoute = (rawRoute, allowedRoutes) => {
|
|
12
|
+
if (typeof rawRoute !== "string")
|
|
13
|
+
return null;
|
|
14
|
+
const trimmed = rawRoute.trim();
|
|
15
|
+
if (!trimmed)
|
|
16
|
+
return null;
|
|
17
|
+
if (allowedRoutes.length === 0)
|
|
18
|
+
return trimmed;
|
|
19
|
+
const direct = allowedRoutes.find((route) => route === trimmed);
|
|
20
|
+
if (direct)
|
|
21
|
+
return direct;
|
|
22
|
+
const lower = trimmed.toLowerCase();
|
|
23
|
+
// 与结构化校验保持一致:大小写不一致时使用工作流声明值,避免命中丢失。
|
|
24
|
+
return allowedRoutes.find((route) => route.toLowerCase() === lower) ?? null;
|
|
25
|
+
};
|
|
26
|
+
const collectRouteBuckets = (content, allowedRoutes) => {
|
|
27
|
+
if (!Array.isArray(content))
|
|
28
|
+
return [];
|
|
29
|
+
const counts = new Map();
|
|
30
|
+
for (const entry of content) {
|
|
31
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry))
|
|
32
|
+
continue;
|
|
33
|
+
const route = normalizeAllowedRoute(entry.route, allowedRoutes);
|
|
34
|
+
if (!route)
|
|
35
|
+
continue;
|
|
36
|
+
entry.route = route;
|
|
37
|
+
counts.set(route, (counts.get(route) ?? 0) + 1);
|
|
38
|
+
}
|
|
39
|
+
return [...counts.entries()].map(([route, count]) => ({ route, count }));
|
|
40
|
+
};
|
|
41
|
+
const createRouteItemManager = (options) => {
|
|
42
|
+
const clearDerivedRouteItemRuns = (item) => {
|
|
43
|
+
const run = options.state.getRun();
|
|
44
|
+
const prefix = `${item.itemKey}::${item.nodeId}:`;
|
|
45
|
+
run.itemRuns = (run.itemRuns ?? []).filter((candidate) => !candidate.itemKey.startsWith(prefix));
|
|
46
|
+
run.groupItemRuns = (run.groupItemRuns ?? []).filter((candidate) => !candidate.itemKey.startsWith(prefix));
|
|
47
|
+
};
|
|
48
|
+
const resetNodeItemRun = (target, status) => {
|
|
49
|
+
(0, state_1.markItemReset)(target, status, ctx("route_reset", { command: "retry_reset" }));
|
|
50
|
+
target.route = null;
|
|
51
|
+
target.attempt = 0;
|
|
52
|
+
target.loopCount = 0;
|
|
53
|
+
target.artifacts = [];
|
|
54
|
+
};
|
|
55
|
+
const resetGroupItemRun = (target, status) => {
|
|
56
|
+
(0, state_1.markGroupItemReset)(target, status, ctx("route_reset", { command: "retry_reset" }));
|
|
57
|
+
target.attempt = 0;
|
|
58
|
+
target.artifacts = [];
|
|
59
|
+
};
|
|
60
|
+
const copyNodeItemRun = (target, source) => {
|
|
61
|
+
target.status = (0, state_machine_1.transitionStatus)(target.status, source.status, "route_backfill");
|
|
62
|
+
target.route = source.route;
|
|
63
|
+
target.attempt = source.attempt;
|
|
64
|
+
target.loopCount = source.loopCount;
|
|
65
|
+
target.wakeAt = source.wakeAt;
|
|
66
|
+
target.startedAt = source.startedAt;
|
|
67
|
+
target.finishedAt = source.finishedAt;
|
|
68
|
+
target.lastError = source.lastError;
|
|
69
|
+
target.artifacts = source.artifacts;
|
|
70
|
+
};
|
|
71
|
+
const copyGroupItemRun = (target, source) => {
|
|
72
|
+
target.status = (0, state_machine_1.transitionStatus)(target.status, source.status, "route_backfill");
|
|
73
|
+
target.attempt = source.attempt;
|
|
74
|
+
target.startedAt = source.startedAt;
|
|
75
|
+
target.finishedAt = source.finishedAt;
|
|
76
|
+
target.lastError = source.lastError;
|
|
77
|
+
target.artifacts = source.artifacts;
|
|
78
|
+
};
|
|
79
|
+
const initializeDerivedRouteItemKey = (sourceItem, derivedItemKey, route) => {
|
|
80
|
+
const run = options.state.getRun();
|
|
81
|
+
options.graph.syncRunGroupsFromWorkflow(run);
|
|
82
|
+
if (!run.itemRuns)
|
|
83
|
+
run.itemRuns = [];
|
|
84
|
+
if (!run.groupItemRuns)
|
|
85
|
+
run.groupItemRuns = [];
|
|
86
|
+
const outgoingEdges = options.graph.getOutgoingEdges(sourceItem.nodeId);
|
|
87
|
+
const isRouteNode = (options.graph.getWorkflowNodeById(sourceItem.nodeId)?.routePolicy?.allowed.length ?? 0) > 0;
|
|
88
|
+
const startTargets = outgoingEdges
|
|
89
|
+
// 分流节点中 yes 是主线语义:只沿普通依赖边初始化;no/自定义值只沿路由边初始化。
|
|
90
|
+
.filter((edge) => (isRouteNode ? (route === routes_1.MAINLINE_ROUTE_VALUE ? edge.when === null : edge.when === route) : !edge.when))
|
|
91
|
+
.map((edge) => edge.to);
|
|
92
|
+
const reachable = options.state.collectReachableEntities(startTargets);
|
|
93
|
+
const ancestors = options.state.collectAncestorEntities([sourceItem.nodeId, ...startTargets]);
|
|
94
|
+
for (const node of run.nodes) {
|
|
95
|
+
let target = options.state.getItemRun(node.id, derivedItemKey);
|
|
96
|
+
if (!target) {
|
|
97
|
+
target = {
|
|
98
|
+
id: (0, node_crypto_1.randomUUID)(),
|
|
99
|
+
nodeId: node.id,
|
|
100
|
+
itemKey: derivedItemKey,
|
|
101
|
+
status: "blocked",
|
|
102
|
+
route: null,
|
|
103
|
+
attempt: 0,
|
|
104
|
+
loopCount: 0,
|
|
105
|
+
wakeAt: null,
|
|
106
|
+
startedAt: null,
|
|
107
|
+
finishedAt: null,
|
|
108
|
+
lastError: null,
|
|
109
|
+
artifacts: [],
|
|
110
|
+
};
|
|
111
|
+
run.itemRuns.push(target);
|
|
112
|
+
}
|
|
113
|
+
const source = options.state.getItemRun(node.id, sourceItem.itemKey);
|
|
114
|
+
if (node.id === sourceItem.nodeId) {
|
|
115
|
+
copyNodeItemRun(target, source ?? sourceItem);
|
|
116
|
+
(0, state_1.markItemSuccess)(target, ctx("route_init_success", { command: "route_backfill" }));
|
|
117
|
+
target.route = route;
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
if (ancestors.nodeIds.has(node.id)) {
|
|
121
|
+
if (source) {
|
|
122
|
+
copyNodeItemRun(target, source);
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
resetNodeItemRun(target, options.state.computeInitialItemStatus(node.id));
|
|
126
|
+
}
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
if (reachable.nodeIds.has(node.id)) {
|
|
130
|
+
resetNodeItemRun(target, options.state.computeInitialItemStatus(node.id));
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
resetNodeItemRun(target, "skipped");
|
|
134
|
+
}
|
|
135
|
+
for (const group of run.groups ?? []) {
|
|
136
|
+
let target = options.state.getGroupItemRun(group.id, derivedItemKey);
|
|
137
|
+
if (!target) {
|
|
138
|
+
target = {
|
|
139
|
+
id: (0, node_crypto_1.randomUUID)(),
|
|
140
|
+
groupId: group.id,
|
|
141
|
+
itemKey: derivedItemKey,
|
|
142
|
+
status: "blocked",
|
|
143
|
+
attempt: 0,
|
|
144
|
+
startedAt: null,
|
|
145
|
+
finishedAt: null,
|
|
146
|
+
lastError: null,
|
|
147
|
+
artifacts: [],
|
|
148
|
+
};
|
|
149
|
+
run.groupItemRuns.push(target);
|
|
150
|
+
}
|
|
151
|
+
const source = options.state.getGroupItemRun(group.id, sourceItem.itemKey);
|
|
152
|
+
if (ancestors.groupIds.has(group.id)) {
|
|
153
|
+
if (source) {
|
|
154
|
+
copyGroupItemRun(target, source);
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
resetGroupItemRun(target, options.state.computeInitialGroupItemStatus(group.id));
|
|
158
|
+
}
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
if (reachable.groupIds.has(group.id)) {
|
|
162
|
+
resetGroupItemRun(target, options.state.computeInitialGroupItemStatus(group.id));
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
resetGroupItemRun(target, "skipped");
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
const applyEnvelopeOutcomeToItem = async (item, envelope, opts) => {
|
|
169
|
+
if (!envelope)
|
|
170
|
+
return;
|
|
171
|
+
const workflowNode = options.graph.getWorkflowNodeById(item.nodeId);
|
|
172
|
+
const allowedRoutes = workflowNode?.routePolicy?.allowed ?? [];
|
|
173
|
+
const isRouteNode = allowedRoutes.length > 0;
|
|
174
|
+
item.route = null;
|
|
175
|
+
if (isRouteNode) {
|
|
176
|
+
clearDerivedRouteItemRuns(item);
|
|
177
|
+
const routeBuckets = collectRouteBuckets(envelope.artifacts[0]?.content, allowedRoutes);
|
|
178
|
+
for (const bucket of routeBuckets) {
|
|
179
|
+
const derivedItemKey = (0, identity_1.buildDerivedRouteItemKey)(item.itemKey, item.nodeId, bucket.route);
|
|
180
|
+
initializeDerivedRouteItemKey(item, derivedItemKey, bucket.route);
|
|
181
|
+
const nextItem = options.state.getItemRun(item.nodeId, derivedItemKey);
|
|
182
|
+
if (!nextItem)
|
|
183
|
+
continue;
|
|
184
|
+
(0, state_1.markItemSuccess)(nextItem, ctx("route_hit", { command: "route_backfill" }));
|
|
185
|
+
nextItem.route = bucket.route;
|
|
186
|
+
nextItem.attempt = Math.max(nextItem.attempt, item.attempt);
|
|
187
|
+
nextItem.startedAt = item.startedAt;
|
|
188
|
+
nextItem.finishedAt = item.finishedAt ?? new Date().toISOString();
|
|
189
|
+
nextItem.wakeAt = null;
|
|
190
|
+
nextItem.artifacts = item.artifacts;
|
|
191
|
+
if (!opts?.suppressOutgoing) {
|
|
192
|
+
for (const edge of options.graph.getOutgoingEdges(item.nodeId)) {
|
|
193
|
+
if (bucket.route === routes_1.MAINLINE_ROUTE_VALUE)
|
|
194
|
+
continue;
|
|
195
|
+
// 路由节点只按命中的 route 边推进,普通边在此一律忽略,避免主线被隐式直通。
|
|
196
|
+
if (edge.when !== bucket.route)
|
|
197
|
+
continue;
|
|
198
|
+
if (options.graph.isGroupId(edge.to)) {
|
|
199
|
+
options.state.ensureGroupItemKeyInitialized(derivedItemKey);
|
|
200
|
+
const downstreamGroup = options.state.getGroupItemRun(edge.to, derivedItemKey);
|
|
201
|
+
if (downstreamGroup && (0, readiness_state_1.canPromoteToQueuedByDependency)(downstreamGroup)) {
|
|
202
|
+
(0, state_1.markGroupItemQueued)(downstreamGroup, ctx("route_downstream"));
|
|
203
|
+
}
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
const downstream = options.state.getItemRun(edge.to, derivedItemKey);
|
|
207
|
+
if (!downstream)
|
|
208
|
+
continue;
|
|
209
|
+
if ((0, readiness_state_1.canPromoteToQueuedByDependency)(downstream)) {
|
|
210
|
+
(0, state_1.markItemQueued)(downstream, ctx("route_downstream"));
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
options.runtimeStore.pushTimeline(`分流命中: ${item.nodeId}#${item.itemKey} -> ${bucket.route} (${bucket.count} 条)`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
const sleepUntil = envelope.control?.sleepUntil;
|
|
218
|
+
if (typeof sleepUntil === "string" && sleepUntil.trim()) {
|
|
219
|
+
const parsed = Date.parse(sleepUntil);
|
|
220
|
+
if (Number.isFinite(parsed)) {
|
|
221
|
+
const wakeAt = new Date(parsed).toISOString();
|
|
222
|
+
(0, state_1.markItemWaiting)(item, { reason: "sleep_until", wakeAt });
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
if (!opts?.suppressOutgoing && !isRouteNode) {
|
|
226
|
+
for (const edge of options.graph.getOutgoingEdges(item.nodeId)) {
|
|
227
|
+
if (edge.when)
|
|
228
|
+
continue;
|
|
229
|
+
if (options.graph.isCrossBranchEdge({ from: item.nodeId, to: edge.to, when: null })) {
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
if (options.graph.isGroupId(edge.to)) {
|
|
233
|
+
options.state.ensureGroupItemKeyInitialized(item.itemKey);
|
|
234
|
+
const downstreamGroup = options.state.getGroupItemRun(edge.to, item.itemKey);
|
|
235
|
+
if (downstreamGroup && (0, readiness_state_1.canPromoteToQueuedByDependency)(downstreamGroup)) {
|
|
236
|
+
(0, state_1.markGroupItemQueued)(downstreamGroup, ctx("downstream_promote"));
|
|
237
|
+
}
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
const downstream = options.state.getItemRun(edge.to, item.itemKey);
|
|
241
|
+
if (!downstream)
|
|
242
|
+
continue;
|
|
243
|
+
if ((0, readiness_state_1.canPromoteToQueuedByDependency)(downstream)) {
|
|
244
|
+
(0, state_1.markItemQueued)(downstream, ctx("downstream_promote"));
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
return {
|
|
250
|
+
applyEnvelopeOutcomeToItem,
|
|
251
|
+
};
|
|
252
|
+
};
|
|
253
|
+
exports.createRouteItemManager = createRouteItemManager;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createRunAbortController = void 0;
|
|
4
|
+
const createRunAbortController = () => {
|
|
5
|
+
const nodeExecutionControllers = new Map();
|
|
6
|
+
const drainControllers = new Map();
|
|
7
|
+
const registerController = (runId, ac, sessionId) => {
|
|
8
|
+
let controllers = nodeExecutionControllers.get(runId);
|
|
9
|
+
if (!controllers) {
|
|
10
|
+
controllers = new Set();
|
|
11
|
+
nodeExecutionControllers.set(runId, controllers);
|
|
12
|
+
}
|
|
13
|
+
const entry = { ac, sessionId };
|
|
14
|
+
controllers.add(entry);
|
|
15
|
+
return entry;
|
|
16
|
+
};
|
|
17
|
+
const unregisterController = (runId, entry) => {
|
|
18
|
+
const controllers = nodeExecutionControllers.get(runId);
|
|
19
|
+
if (!controllers)
|
|
20
|
+
return;
|
|
21
|
+
controllers.delete(entry);
|
|
22
|
+
if (controllers.size === 0) {
|
|
23
|
+
nodeExecutionControllers.delete(runId);
|
|
24
|
+
}
|
|
25
|
+
entry.ac.abort();
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* 中止指定流水线运行的所有节点执行。
|
|
29
|
+
* 1. 向每个活跃节点的远端 agent 会话发送 "/stop" 命令(fire-and-forget)
|
|
30
|
+
* 2. 触发本地 AbortController 中断轮询/排水循环
|
|
31
|
+
*/
|
|
32
|
+
const abortRunControllers = (runId, client) => {
|
|
33
|
+
const controllers = nodeExecutionControllers.get(runId);
|
|
34
|
+
if (controllers) {
|
|
35
|
+
const sessionIds = new Set();
|
|
36
|
+
for (const entry of controllers) {
|
|
37
|
+
entry.ac.abort();
|
|
38
|
+
sessionIds.add(entry.sessionId);
|
|
39
|
+
}
|
|
40
|
+
nodeExecutionControllers.delete(runId);
|
|
41
|
+
for (const sessionId of sessionIds) {
|
|
42
|
+
client.sendReq("chat.send", { sessionKey: sessionId, message: "/stop" }, { sideEffect: true })
|
|
43
|
+
.catch(() => { });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
const dc = drainControllers.get(runId);
|
|
47
|
+
if (dc) {
|
|
48
|
+
dc.abort();
|
|
49
|
+
drainControllers.delete(runId);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* 获取或创建用于 drainPipeline 的中止信号。
|
|
54
|
+
* 每次新 run 会创建新的 AbortController,确保 stop/retry 只中断当前运行。
|
|
55
|
+
*/
|
|
56
|
+
const getOrCreateDrainSignal = (runId) => {
|
|
57
|
+
let dc = drainControllers.get(runId);
|
|
58
|
+
if (!dc) {
|
|
59
|
+
dc = new AbortController();
|
|
60
|
+
drainControllers.set(runId, dc);
|
|
61
|
+
}
|
|
62
|
+
return dc.signal;
|
|
63
|
+
};
|
|
64
|
+
return { registerController, unregisterController, abortRunControllers, getOrCreateDrainSignal };
|
|
65
|
+
};
|
|
66
|
+
exports.createRunAbortController = createRunAbortController;
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createRunStateHelpers = void 0;
|
|
4
|
+
const node_crypto_1 = require("node:crypto");
|
|
5
|
+
const dependency_check_1 = require("./dependency-check");
|
|
6
|
+
const state_machine_1 = require("../state-machine");
|
|
7
|
+
const createRunStateHelpers = (options) => {
|
|
8
|
+
const getRun = () => options.runtimeStore.getRun();
|
|
9
|
+
const getNodeById = (nodeId) => getRun().nodes.find((node) => node.id === nodeId) ?? null;
|
|
10
|
+
const getGroupById = (groupId) => (getRun().groups ?? []).find((group) => group.id === groupId) ?? null;
|
|
11
|
+
const getItemRun = (nodeId, itemKey) => (getRun().itemRuns ?? []).find((item) => item.nodeId === nodeId && item.itemKey === itemKey) ?? null;
|
|
12
|
+
const getGroupItemRun = (groupId, itemKey) => (getRun().groupItemRuns ?? []).find((item) => item.groupId === groupId && item.itemKey === itemKey) ?? null;
|
|
13
|
+
const computeInitialItemStatus = (nodeId) => {
|
|
14
|
+
if (!options.graph.isWorkflowNodeEnabled(nodeId))
|
|
15
|
+
return "skipped";
|
|
16
|
+
if (options.graph.getParallelGroupByMemberNodeId(nodeId))
|
|
17
|
+
return "blocked";
|
|
18
|
+
const incoming = options.graph.getIncomingEdges(nodeId);
|
|
19
|
+
return incoming.length === 0 ? "queued" : "blocked";
|
|
20
|
+
};
|
|
21
|
+
const computeInitialGroupItemStatus = (groupId) => {
|
|
22
|
+
const incoming = options.graph.getIncomingEdges(groupId);
|
|
23
|
+
return incoming.length === 0 ? "queued" : "blocked";
|
|
24
|
+
};
|
|
25
|
+
const ensureGroupItemKeyInitialized = (itemKey) => {
|
|
26
|
+
const run = getRun();
|
|
27
|
+
options.graph.syncRunGroupsFromWorkflow(run);
|
|
28
|
+
if (!run.groupItemRuns)
|
|
29
|
+
run.groupItemRuns = [];
|
|
30
|
+
for (const group of run.groups ?? []) {
|
|
31
|
+
const existed = run.groupItemRuns.find((item) => item.groupId === group.id && item.itemKey === itemKey);
|
|
32
|
+
if (existed)
|
|
33
|
+
continue;
|
|
34
|
+
run.groupItemRuns.push({
|
|
35
|
+
id: (0, node_crypto_1.randomUUID)(),
|
|
36
|
+
groupId: group.id,
|
|
37
|
+
itemKey,
|
|
38
|
+
status: computeInitialGroupItemStatus(group.id),
|
|
39
|
+
attempt: 0,
|
|
40
|
+
startedAt: null,
|
|
41
|
+
finishedAt: null,
|
|
42
|
+
lastError: null,
|
|
43
|
+
artifacts: [],
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
const ensureItemRuns = () => {
|
|
48
|
+
const run = getRun();
|
|
49
|
+
if (!run.itemRuns)
|
|
50
|
+
run.itemRuns = [];
|
|
51
|
+
options.graph.syncRunGroupsFromWorkflow(run);
|
|
52
|
+
if (run.itemRuns.length === 0) {
|
|
53
|
+
run.itemRuns = options.graph.getTemplateNodes().flatMap((node) => {
|
|
54
|
+
const status = computeInitialItemStatus(node.id);
|
|
55
|
+
return options.defaultItemKeys.map((itemKey) => ({
|
|
56
|
+
id: (0, node_crypto_1.randomUUID)(),
|
|
57
|
+
nodeId: node.id,
|
|
58
|
+
itemKey,
|
|
59
|
+
status,
|
|
60
|
+
route: null,
|
|
61
|
+
attempt: 0,
|
|
62
|
+
loopCount: 0,
|
|
63
|
+
wakeAt: null,
|
|
64
|
+
startedAt: null,
|
|
65
|
+
finishedAt: null,
|
|
66
|
+
lastError: null,
|
|
67
|
+
artifacts: [],
|
|
68
|
+
}));
|
|
69
|
+
});
|
|
70
|
+
for (const itemKey of options.defaultItemKeys) {
|
|
71
|
+
ensureGroupItemKeyInitialized(itemKey);
|
|
72
|
+
}
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const knownNodeIds = new Set(run.nodes.map((node) => node.id));
|
|
76
|
+
run.itemRuns = run.itemRuns.filter((item) => knownNodeIds.has(item.nodeId));
|
|
77
|
+
};
|
|
78
|
+
const ensureItemKeyInitialized = (itemKey) => {
|
|
79
|
+
const run = getRun();
|
|
80
|
+
if (!run.itemRuns)
|
|
81
|
+
run.itemRuns = [];
|
|
82
|
+
for (const node of run.nodes) {
|
|
83
|
+
const existed = run.itemRuns.find((item) => item.nodeId === node.id && item.itemKey === itemKey);
|
|
84
|
+
if (existed)
|
|
85
|
+
continue;
|
|
86
|
+
run.itemRuns.push({
|
|
87
|
+
id: (0, node_crypto_1.randomUUID)(),
|
|
88
|
+
nodeId: node.id,
|
|
89
|
+
itemKey,
|
|
90
|
+
status: computeInitialItemStatus(node.id),
|
|
91
|
+
route: null,
|
|
92
|
+
attempt: 0,
|
|
93
|
+
loopCount: 0,
|
|
94
|
+
wakeAt: null,
|
|
95
|
+
startedAt: null,
|
|
96
|
+
finishedAt: null,
|
|
97
|
+
lastError: null,
|
|
98
|
+
artifacts: [],
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
ensureGroupItemKeyInitialized(itemKey);
|
|
102
|
+
};
|
|
103
|
+
const depCheckContext = {
|
|
104
|
+
isCrossBranchEdge: (edge) => options.graph.isCrossBranchEdge(edge),
|
|
105
|
+
isGroupId: (id) => options.graph.isGroupId(id),
|
|
106
|
+
isWorkflowNodeEnabled: (id) => options.graph.isWorkflowNodeEnabled(id),
|
|
107
|
+
isRoutePolicyNode: (id) => (options.graph.getWorkflowNodeById(id)?.routePolicy?.allowed.length ?? 0) > 0,
|
|
108
|
+
getGroupItemRun: (groupId, itemKey) => getGroupItemRun(groupId, itemKey),
|
|
109
|
+
getItemRun: (nodeId, itemKey) => getItemRun(nodeId, itemKey),
|
|
110
|
+
};
|
|
111
|
+
const isDependencySatisfied = (itemKey, edge) => (0, dependency_check_1.isDependencySatisfied)(itemKey, edge, depCheckContext);
|
|
112
|
+
const getEffectiveDependencyIdsForNodeItem = (nodeId, itemKey) => {
|
|
113
|
+
const directDependencyIds = options.graph.getIncomingEdges(nodeId)
|
|
114
|
+
.filter((edge) => isDependencySatisfied(itemKey, edge))
|
|
115
|
+
.map((edge) => edge.from);
|
|
116
|
+
const groupId = options.graph.getWorkflowNodeById(nodeId)?.parallelGroupId?.trim();
|
|
117
|
+
if (!groupId)
|
|
118
|
+
return [...new Set(directDependencyIds)];
|
|
119
|
+
const groupDependencyIds = options.graph.getIncomingEdges(groupId)
|
|
120
|
+
.filter((edge) => isDependencySatisfied(itemKey, edge))
|
|
121
|
+
.map((edge) => edge.from);
|
|
122
|
+
return [...new Set([...directDependencyIds, ...groupDependencyIds])];
|
|
123
|
+
};
|
|
124
|
+
const collectDownstreamSubgraph = (rootNodeId) => {
|
|
125
|
+
const nodeIds = new Set();
|
|
126
|
+
const groupIds = new Set();
|
|
127
|
+
const queue = [rootNodeId];
|
|
128
|
+
const seen = new Set();
|
|
129
|
+
while (queue.length > 0) {
|
|
130
|
+
const current = queue.shift();
|
|
131
|
+
if (!current || seen.has(current))
|
|
132
|
+
continue;
|
|
133
|
+
seen.add(current);
|
|
134
|
+
if (options.graph.isGroupId(current)) {
|
|
135
|
+
groupIds.add(current);
|
|
136
|
+
const group = options.graph.getWorkflowGroupById(current);
|
|
137
|
+
// 并行组本身不是执行节点,但它控制成员节点与后续 join 分支的状态。
|
|
138
|
+
// 回放/打回时必须穿透 group,把成员和 group 后面的节点一起纳入重置范围。
|
|
139
|
+
for (const memberId of group?.members ?? []) {
|
|
140
|
+
queue.push(memberId);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
nodeIds.add(current);
|
|
145
|
+
const ownerGroup = options.graph.getParallelGroupByMemberNodeId(current);
|
|
146
|
+
if (ownerGroup) {
|
|
147
|
+
queue.push(ownerGroup.id);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
for (const edge of options.graph.getOutgoingEdges(current)) {
|
|
151
|
+
if (options.graph.isCrossBranchEdge(edge))
|
|
152
|
+
continue;
|
|
153
|
+
queue.push(edge.to);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return { nodeIds, groupIds };
|
|
157
|
+
};
|
|
158
|
+
const collectReachableEntities = (startIds) => {
|
|
159
|
+
const nodeIds = new Set();
|
|
160
|
+
const groupIds = new Set();
|
|
161
|
+
const queue = [...startIds];
|
|
162
|
+
const seen = new Set();
|
|
163
|
+
while (queue.length > 0) {
|
|
164
|
+
const current = queue.shift();
|
|
165
|
+
if (!current || seen.has(current))
|
|
166
|
+
continue;
|
|
167
|
+
seen.add(current);
|
|
168
|
+
if (options.graph.isGroupId(current)) {
|
|
169
|
+
groupIds.add(current);
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
nodeIds.add(current);
|
|
173
|
+
}
|
|
174
|
+
for (const edge of options.graph.getOutgoingEdges(current)) {
|
|
175
|
+
queue.push(edge.to);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return { nodeIds, groupIds };
|
|
179
|
+
};
|
|
180
|
+
const collectAncestorEntities = (startIds) => {
|
|
181
|
+
const nodeIds = new Set();
|
|
182
|
+
const groupIds = new Set();
|
|
183
|
+
const queue = [...startIds];
|
|
184
|
+
const seen = new Set();
|
|
185
|
+
while (queue.length > 0) {
|
|
186
|
+
const current = queue.shift();
|
|
187
|
+
if (!current || seen.has(current))
|
|
188
|
+
continue;
|
|
189
|
+
seen.add(current);
|
|
190
|
+
if (options.graph.isGroupId(current)) {
|
|
191
|
+
groupIds.add(current);
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
nodeIds.add(current);
|
|
195
|
+
}
|
|
196
|
+
for (const edge of options.graph.getIncomingEdges(current)) {
|
|
197
|
+
queue.push(edge.from);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return { nodeIds, groupIds };
|
|
201
|
+
};
|
|
202
|
+
const resetNodeForReplay = (node, opts) => {
|
|
203
|
+
const run = getRun();
|
|
204
|
+
if (!options.graph.isWorkflowNodeEnabled(node.id)) {
|
|
205
|
+
node.status = (0, state_machine_1.transitionStatus)(node.status, "skipped");
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
const effectiveDepIds = new Set(options.graph.getIncomingEdges(node.id)
|
|
209
|
+
.filter((edge) => !options.graph.isCrossBranchEdge(edge))
|
|
210
|
+
.map((edge) => edge.from));
|
|
211
|
+
const groupId = options.graph.getWorkflowNodeById(node.id)?.parallelGroupId?.trim();
|
|
212
|
+
if (groupId) {
|
|
213
|
+
for (const edge of options.graph.getIncomingEdges(groupId)) {
|
|
214
|
+
if (!options.graph.isCrossBranchEdge(edge)) {
|
|
215
|
+
effectiveDepIds.add(edge.from);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
node.status = (0, state_machine_1.transitionStatus)(node.status, [...effectiveDepIds].every((depId) => {
|
|
220
|
+
if (options.graph.isGroupId(depId)) {
|
|
221
|
+
return (run.groups ?? []).find((group) => group.id === depId)?.status === "success";
|
|
222
|
+
}
|
|
223
|
+
if (!options.graph.isWorkflowNodeEnabled(depId))
|
|
224
|
+
return true;
|
|
225
|
+
return run.nodes.find((current) => current.id === depId)?.status === "success";
|
|
226
|
+
})
|
|
227
|
+
? "queued"
|
|
228
|
+
: "blocked");
|
|
229
|
+
}
|
|
230
|
+
node.artifacts = [];
|
|
231
|
+
node.startedAt = null;
|
|
232
|
+
node.finishedAt = null;
|
|
233
|
+
node.lastError = null;
|
|
234
|
+
if (opts?.clearRejectFeedbacks ?? true) {
|
|
235
|
+
node.rejectFeedbacks = [];
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
return {
|
|
239
|
+
getRun,
|
|
240
|
+
getNodeById,
|
|
241
|
+
getGroupById,
|
|
242
|
+
getItemRun,
|
|
243
|
+
getGroupItemRun,
|
|
244
|
+
computeInitialItemStatus,
|
|
245
|
+
computeInitialGroupItemStatus,
|
|
246
|
+
ensureGroupItemKeyInitialized,
|
|
247
|
+
ensureItemRuns,
|
|
248
|
+
ensureItemKeyInitialized,
|
|
249
|
+
isDependencySatisfied,
|
|
250
|
+
getEffectiveDependencyIdsForNodeItem,
|
|
251
|
+
collectDownstreamSubgraph,
|
|
252
|
+
collectReachableEntities,
|
|
253
|
+
collectAncestorEntities,
|
|
254
|
+
resetNodeForReplay,
|
|
255
|
+
};
|
|
256
|
+
};
|
|
257
|
+
exports.createRunStateHelpers = createRunStateHelpers;
|