yaml-flow 1.0.0 → 2.1.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/README.md +705 -225
- package/dist/batch/index.cjs +109 -0
- package/dist/batch/index.cjs.map +1 -0
- package/dist/batch/index.d.cts +126 -0
- package/dist/batch/index.d.ts +126 -0
- package/dist/batch/index.js +107 -0
- package/dist/batch/index.js.map +1 -0
- package/dist/config/index.cjs +80 -0
- package/dist/config/index.cjs.map +1 -0
- package/dist/config/index.d.cts +71 -0
- package/dist/config/index.d.ts +71 -0
- package/dist/config/index.js +77 -0
- package/dist/config/index.js.map +1 -0
- package/dist/constants-D1fTEbbM.d.cts +330 -0
- package/dist/constants-D1fTEbbM.d.ts +330 -0
- package/dist/event-graph/index.cjs +895 -0
- package/dist/event-graph/index.cjs.map +1 -0
- package/dist/event-graph/index.d.cts +53 -0
- package/dist/event-graph/index.d.ts +53 -0
- package/dist/event-graph/index.js +855 -0
- package/dist/event-graph/index.js.map +1 -0
- package/dist/index.cjs +1309 -312
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -2
- package/dist/index.d.ts +5 -2
- package/dist/index.js +1271 -306
- package/dist/index.js.map +1 -1
- package/dist/step-machine/index.cjs +513 -0
- package/dist/step-machine/index.cjs.map +1 -0
- package/dist/step-machine/index.d.cts +77 -0
- package/dist/step-machine/index.d.ts +77 -0
- package/dist/step-machine/index.js +502 -0
- package/dist/step-machine/index.js.map +1 -0
- package/dist/stores/file.cjs.map +1 -1
- package/dist/stores/file.d.cts +4 -4
- package/dist/stores/file.d.ts +4 -4
- package/dist/stores/file.js.map +1 -1
- package/dist/stores/index.cjs +232 -0
- package/dist/stores/index.cjs.map +1 -0
- package/dist/stores/index.d.cts +4 -0
- package/dist/stores/index.d.ts +4 -0
- package/dist/stores/index.js +228 -0
- package/dist/stores/index.js.map +1 -0
- package/dist/stores/localStorage.cjs.map +1 -1
- package/dist/stores/localStorage.d.cts +4 -4
- package/dist/stores/localStorage.d.ts +4 -4
- package/dist/stores/localStorage.js.map +1 -1
- package/dist/stores/memory.cjs.map +1 -1
- package/dist/stores/memory.d.cts +4 -4
- package/dist/stores/memory.d.ts +4 -4
- package/dist/stores/memory.js.map +1 -1
- package/dist/types-FZ_eyErS.d.cts +115 -0
- package/dist/types-FZ_eyErS.d.ts +115 -0
- package/package.json +26 -6
- package/dist/core/index.cjs +0 -557
- package/dist/core/index.cjs.map +0 -1
- package/dist/core/index.d.cts +0 -102
- package/dist/core/index.d.ts +0 -102
- package/dist/core/index.js +0 -549
- package/dist/core/index.js.map +0 -1
- package/dist/types-BoWndaAJ.d.cts +0 -237
- package/dist/types-BoWndaAJ.d.ts +0 -237
|
@@ -0,0 +1,895 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/event-graph/constants.ts
|
|
4
|
+
var TASK_STATUS = {
|
|
5
|
+
NOT_STARTED: "not-started",
|
|
6
|
+
RUNNING: "running",
|
|
7
|
+
COMPLETED: "completed",
|
|
8
|
+
FAILED: "failed",
|
|
9
|
+
INACTIVATED: "inactivated"
|
|
10
|
+
};
|
|
11
|
+
var EXECUTION_STATUS = {
|
|
12
|
+
CREATED: "created",
|
|
13
|
+
RUNNING: "running",
|
|
14
|
+
PAUSED: "paused",
|
|
15
|
+
STOPPED: "stopped",
|
|
16
|
+
COMPLETED: "completed",
|
|
17
|
+
FAILED: "failed"
|
|
18
|
+
};
|
|
19
|
+
var COMPLETION_STRATEGIES = {
|
|
20
|
+
ALL_TASKS_DONE: "all-tasks-done",
|
|
21
|
+
ALL_OUTPUTS_DONE: "all-outputs-done",
|
|
22
|
+
ONLY_RESOLVED: "only-resolved",
|
|
23
|
+
GOAL_REACHED: "goal-reached",
|
|
24
|
+
MANUAL: "manual"
|
|
25
|
+
};
|
|
26
|
+
var EXECUTION_MODES = {
|
|
27
|
+
DEPENDENCY_MODE: "dependency-mode",
|
|
28
|
+
ELIGIBILITY_MODE: "eligibility-mode"
|
|
29
|
+
};
|
|
30
|
+
var CONFLICT_STRATEGIES = {
|
|
31
|
+
ALPHABETICAL: "alphabetical",
|
|
32
|
+
PRIORITY_FIRST: "priority-first",
|
|
33
|
+
DURATION_FIRST: "duration-first",
|
|
34
|
+
COST_OPTIMIZED: "cost-optimized",
|
|
35
|
+
RESOURCE_AWARE: "resource-aware",
|
|
36
|
+
RANDOM_SELECT: "random-select",
|
|
37
|
+
USER_CHOICE: "user-choice",
|
|
38
|
+
PARALLEL_ALL: "parallel-all",
|
|
39
|
+
SKIP_CONFLICTS: "skip-conflicts",
|
|
40
|
+
ROUND_ROBIN: "round-robin"
|
|
41
|
+
};
|
|
42
|
+
var DEFAULTS = {
|
|
43
|
+
EXECUTION_MODE: "eligibility-mode",
|
|
44
|
+
CONFLICT_STRATEGY: "alphabetical",
|
|
45
|
+
COMPLETION_STRATEGY: "all-outputs-done",
|
|
46
|
+
MAX_ITERATIONS: 1e3
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
// src/event-graph/graph-helpers.ts
|
|
50
|
+
function getProvides(task) {
|
|
51
|
+
if (!task) return [];
|
|
52
|
+
if (Array.isArray(task.provides)) return task.provides;
|
|
53
|
+
return [];
|
|
54
|
+
}
|
|
55
|
+
function getRequires(task) {
|
|
56
|
+
if (!task) return [];
|
|
57
|
+
if (Array.isArray(task.requires)) return task.requires;
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
function getAllTasks(graph) {
|
|
61
|
+
return graph.tasks ?? {};
|
|
62
|
+
}
|
|
63
|
+
function getTask(graph, taskName) {
|
|
64
|
+
return graph.tasks[taskName];
|
|
65
|
+
}
|
|
66
|
+
function hasTask(graph, taskName) {
|
|
67
|
+
return taskName in graph.tasks;
|
|
68
|
+
}
|
|
69
|
+
function isNonActiveTask(taskState) {
|
|
70
|
+
if (!taskState) return false;
|
|
71
|
+
return taskState.status === TASK_STATUS.FAILED || taskState.status === TASK_STATUS.INACTIVATED;
|
|
72
|
+
}
|
|
73
|
+
function isTaskCompleted(taskState) {
|
|
74
|
+
return taskState?.status === TASK_STATUS.COMPLETED;
|
|
75
|
+
}
|
|
76
|
+
function isTaskRunning(taskState) {
|
|
77
|
+
return taskState?.status === TASK_STATUS.RUNNING;
|
|
78
|
+
}
|
|
79
|
+
function isRepeatableTask(taskConfig) {
|
|
80
|
+
return taskConfig.repeatable === true || typeof taskConfig.repeatable === "object" && taskConfig.repeatable !== null;
|
|
81
|
+
}
|
|
82
|
+
function getRepeatableMax(taskConfig) {
|
|
83
|
+
if (taskConfig.repeatable === true) return void 0;
|
|
84
|
+
if (typeof taskConfig.repeatable === "object" && taskConfig.repeatable !== null) {
|
|
85
|
+
return taskConfig.repeatable.max;
|
|
86
|
+
}
|
|
87
|
+
return void 0;
|
|
88
|
+
}
|
|
89
|
+
function computeAvailableOutputs(graph, taskStates) {
|
|
90
|
+
const outputs = /* @__PURE__ */ new Set();
|
|
91
|
+
for (const [taskName, taskState] of Object.entries(taskStates)) {
|
|
92
|
+
if (taskState.status === TASK_STATUS.COMPLETED) {
|
|
93
|
+
const taskConfig = graph.tasks[taskName];
|
|
94
|
+
if (taskConfig) {
|
|
95
|
+
const provides = getProvides(taskConfig);
|
|
96
|
+
provides.forEach((output) => outputs.add(output));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return Array.from(outputs);
|
|
101
|
+
}
|
|
102
|
+
function groupTasksByProvides(candidateTaskNames, tasks) {
|
|
103
|
+
const outputGroups = {};
|
|
104
|
+
candidateTaskNames.forEach((taskName) => {
|
|
105
|
+
const task = tasks[taskName];
|
|
106
|
+
if (!task) return;
|
|
107
|
+
const provides = getProvides(task);
|
|
108
|
+
provides.forEach((output) => {
|
|
109
|
+
if (!outputGroups[output]) {
|
|
110
|
+
outputGroups[output] = [];
|
|
111
|
+
}
|
|
112
|
+
outputGroups[output].push(taskName);
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
return outputGroups;
|
|
116
|
+
}
|
|
117
|
+
function hasOutputConflict(taskName, taskProvides, candidates, tasks) {
|
|
118
|
+
for (const otherName of candidates) {
|
|
119
|
+
if (otherName === taskName) continue;
|
|
120
|
+
const otherProvides = getProvides(tasks[otherName]);
|
|
121
|
+
const overlapping = taskProvides.some((output) => otherProvides.includes(output));
|
|
122
|
+
if (overlapping) return true;
|
|
123
|
+
}
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
function addKeyToProvides(task, key) {
|
|
127
|
+
const current = getProvides(task);
|
|
128
|
+
if (current.includes(key)) return task;
|
|
129
|
+
return { ...task, provides: [...current, key] };
|
|
130
|
+
}
|
|
131
|
+
function removeKeyFromProvides(task, key) {
|
|
132
|
+
const current = getProvides(task);
|
|
133
|
+
return { ...task, provides: current.filter((p) => p !== key) };
|
|
134
|
+
}
|
|
135
|
+
function addKeyToRequires(task, key) {
|
|
136
|
+
const current = getRequires(task);
|
|
137
|
+
if (current.includes(key)) return task;
|
|
138
|
+
return { ...task, requires: [...current, key] };
|
|
139
|
+
}
|
|
140
|
+
function removeKeyFromRequires(task, key) {
|
|
141
|
+
const current = getRequires(task);
|
|
142
|
+
return { ...task, requires: current.filter((r) => r !== key) };
|
|
143
|
+
}
|
|
144
|
+
function addDynamicTask(graph, taskName, taskConfig) {
|
|
145
|
+
return {
|
|
146
|
+
...graph,
|
|
147
|
+
tasks: {
|
|
148
|
+
...graph.tasks,
|
|
149
|
+
[taskName]: taskConfig
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
function createDefaultTaskState() {
|
|
154
|
+
return {
|
|
155
|
+
status: "not-started",
|
|
156
|
+
executionCount: 0,
|
|
157
|
+
retryCount: 0,
|
|
158
|
+
lastEpoch: 0,
|
|
159
|
+
messages: [],
|
|
160
|
+
progress: null
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
function createInitialExecutionState(graph, executionId) {
|
|
164
|
+
const tasks = {};
|
|
165
|
+
for (const taskName of Object.keys(graph.tasks)) {
|
|
166
|
+
tasks[taskName] = createDefaultTaskState();
|
|
167
|
+
}
|
|
168
|
+
return {
|
|
169
|
+
status: "running",
|
|
170
|
+
tasks,
|
|
171
|
+
availableOutputs: [],
|
|
172
|
+
stuckDetection: { is_stuck: false, stuck_description: null, outputs_unresolvable: [], tasks_blocked: [] },
|
|
173
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
174
|
+
executionId,
|
|
175
|
+
executionConfig: {
|
|
176
|
+
executionMode: graph.settings.execution_mode ?? "eligibility-mode",
|
|
177
|
+
conflictStrategy: graph.settings.conflict_strategy ?? "alphabetical",
|
|
178
|
+
completionStrategy: graph.settings.completion
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// src/event-graph/conflict-resolution.ts
|
|
184
|
+
function selectBestAlternative(alternatives, graphTasks, _executionState, strategy) {
|
|
185
|
+
switch (strategy) {
|
|
186
|
+
case "alphabetical":
|
|
187
|
+
return selectByAlphabetical(alternatives);
|
|
188
|
+
case "priority-first":
|
|
189
|
+
return selectByPriorityFirst(alternatives, graphTasks);
|
|
190
|
+
case "duration-first":
|
|
191
|
+
return selectByDurationFirst(alternatives, graphTasks);
|
|
192
|
+
case "cost-optimized":
|
|
193
|
+
return selectByCostOptimized(alternatives, graphTasks);
|
|
194
|
+
case "resource-aware":
|
|
195
|
+
return selectByResourceAware(alternatives, graphTasks);
|
|
196
|
+
case "round-robin":
|
|
197
|
+
return selectByRoundRobin(alternatives, _executionState);
|
|
198
|
+
default:
|
|
199
|
+
return selectByAlphabetical(alternatives);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
function selectByAlphabetical(alternatives) {
|
|
203
|
+
return [...alternatives].sort((a, b) => a.localeCompare(b))[0];
|
|
204
|
+
}
|
|
205
|
+
function selectByPriorityFirst(alternatives, graphTasks) {
|
|
206
|
+
return [...alternatives].sort((a, b) => {
|
|
207
|
+
const pA = graphTasks[a]?.priority ?? 0;
|
|
208
|
+
const pB = graphTasks[b]?.priority ?? 0;
|
|
209
|
+
if (pA !== pB) return pB - pA;
|
|
210
|
+
const dA = getEstimatedDuration(graphTasks[a]);
|
|
211
|
+
const dB = getEstimatedDuration(graphTasks[b]);
|
|
212
|
+
if (dA !== dB) return dA - dB;
|
|
213
|
+
return a.localeCompare(b);
|
|
214
|
+
})[0];
|
|
215
|
+
}
|
|
216
|
+
function selectByDurationFirst(alternatives, graphTasks) {
|
|
217
|
+
return [...alternatives].sort((a, b) => {
|
|
218
|
+
const dA = getEstimatedDuration(graphTasks[a]);
|
|
219
|
+
const dB = getEstimatedDuration(graphTasks[b]);
|
|
220
|
+
if (dA !== dB) return dA - dB;
|
|
221
|
+
const pA = graphTasks[a]?.priority ?? 0;
|
|
222
|
+
const pB = graphTasks[b]?.priority ?? 0;
|
|
223
|
+
if (pA !== pB) return pB - pA;
|
|
224
|
+
return a.localeCompare(b);
|
|
225
|
+
})[0];
|
|
226
|
+
}
|
|
227
|
+
function selectByCostOptimized(alternatives, graphTasks) {
|
|
228
|
+
return [...alternatives].sort((a, b) => {
|
|
229
|
+
const cA = graphTasks[a]?.estimatedCost ?? 0;
|
|
230
|
+
const cB = graphTasks[b]?.estimatedCost ?? 0;
|
|
231
|
+
if (cA !== cB) return cA - cB;
|
|
232
|
+
const pA = graphTasks[a]?.priority ?? 0;
|
|
233
|
+
const pB = graphTasks[b]?.priority ?? 0;
|
|
234
|
+
if (pA !== pB) return pB - pA;
|
|
235
|
+
return a.localeCompare(b);
|
|
236
|
+
})[0];
|
|
237
|
+
}
|
|
238
|
+
function selectByResourceAware(alternatives, graphTasks) {
|
|
239
|
+
return [...alternatives].sort((a, b) => {
|
|
240
|
+
const rA = graphTasks[a]?.estimatedResources?.cpu ?? 1;
|
|
241
|
+
const rB = graphTasks[b]?.estimatedResources?.cpu ?? 1;
|
|
242
|
+
if (rA !== rB) return rA - rB;
|
|
243
|
+
const pA = graphTasks[a]?.priority ?? 0;
|
|
244
|
+
const pB = graphTasks[b]?.priority ?? 0;
|
|
245
|
+
if (pA !== pB) return pB - pA;
|
|
246
|
+
return a.localeCompare(b);
|
|
247
|
+
})[0];
|
|
248
|
+
}
|
|
249
|
+
function selectByRoundRobin(alternatives, executionState) {
|
|
250
|
+
const totalExecs = Object.values(executionState.tasks).reduce((sum, t) => sum + t.executionCount, 0);
|
|
251
|
+
const sorted = [...alternatives].sort();
|
|
252
|
+
return sorted[totalExecs % sorted.length];
|
|
253
|
+
}
|
|
254
|
+
function getEstimatedDuration(taskConfig) {
|
|
255
|
+
return taskConfig?.estimatedDuration ?? Infinity;
|
|
256
|
+
}
|
|
257
|
+
function getNonConflictingTasks(candidates, graphTasks) {
|
|
258
|
+
return candidates.filter((taskName) => {
|
|
259
|
+
const provides = getProvides(graphTasks[taskName]);
|
|
260
|
+
return !hasOutputConflict(taskName, provides, candidates, graphTasks);
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
function selectRandomTasks(candidates, graphTasks) {
|
|
264
|
+
const outputGroups = groupTasksByProvides(candidates, graphTasks);
|
|
265
|
+
const selected = [];
|
|
266
|
+
for (const groupTasks of Object.values(outputGroups)) {
|
|
267
|
+
if (groupTasks.length === 1) {
|
|
268
|
+
selected.push(...groupTasks);
|
|
269
|
+
} else {
|
|
270
|
+
const idx = Math.floor(Math.random() * groupTasks.length);
|
|
271
|
+
selected.push(groupTasks[idx]);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
const nonConflicting = getNonConflictingTasks(candidates, graphTasks);
|
|
275
|
+
nonConflicting.forEach((t) => {
|
|
276
|
+
if (!selected.includes(t)) selected.push(t);
|
|
277
|
+
});
|
|
278
|
+
return selected;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// src/event-graph/completion.ts
|
|
282
|
+
function isExecutionComplete(graph, state) {
|
|
283
|
+
const strategy = state.executionConfig.completionStrategy;
|
|
284
|
+
switch (strategy) {
|
|
285
|
+
case "all-tasks-done":
|
|
286
|
+
return checkAllTasksDone(graph, state);
|
|
287
|
+
case "all-outputs-done":
|
|
288
|
+
return checkAllOutputsDone(graph, state);
|
|
289
|
+
case "only-resolved":
|
|
290
|
+
return checkOnlyResolved(graph, state);
|
|
291
|
+
case "goal-reached":
|
|
292
|
+
return checkGoalReached(graph, state);
|
|
293
|
+
case "manual":
|
|
294
|
+
return { isComplete: false, expectedCompletion: { taskNames: [], outputs: [] } };
|
|
295
|
+
default:
|
|
296
|
+
return checkAllOutputsDone(graph, state);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
function checkAllTasksDone(graph, state) {
|
|
300
|
+
const graphTasks = getAllTasks(graph);
|
|
301
|
+
const allTaskNames = Object.keys(graphTasks);
|
|
302
|
+
if (allTaskNames.length === 0) {
|
|
303
|
+
return { isComplete: true, expectedCompletion: { taskNames: [], outputs: [] } };
|
|
304
|
+
}
|
|
305
|
+
const allDone = allTaskNames.every((taskName) => {
|
|
306
|
+
const taskState = state.tasks[taskName];
|
|
307
|
+
return taskState?.status === TASK_STATUS.COMPLETED || isNonActiveTask(taskState);
|
|
308
|
+
});
|
|
309
|
+
return {
|
|
310
|
+
isComplete: allDone,
|
|
311
|
+
expectedCompletion: { taskNames: allTaskNames, outputs: [] }
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
function checkAllOutputsDone(graph, state) {
|
|
315
|
+
const graphTasks = getAllTasks(graph);
|
|
316
|
+
const allPossibleOutputs = /* @__PURE__ */ new Set();
|
|
317
|
+
for (const taskConfig of Object.values(graphTasks)) {
|
|
318
|
+
getProvides(taskConfig).forEach((output) => allPossibleOutputs.add(output));
|
|
319
|
+
}
|
|
320
|
+
const availableOutputs = computeAvailableOutputs(graph, state.tasks);
|
|
321
|
+
const allProduced = [...allPossibleOutputs].every((output) => availableOutputs.includes(output));
|
|
322
|
+
return {
|
|
323
|
+
isComplete: allProduced,
|
|
324
|
+
expectedCompletion: { taskNames: [], outputs: [...allPossibleOutputs] }
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
function checkOnlyResolved(graph, state) {
|
|
328
|
+
const graphTasks = getAllTasks(graph);
|
|
329
|
+
const availableOutputs = computeAvailableOutputs(graph, state.tasks);
|
|
330
|
+
const allPossibleOutputs = /* @__PURE__ */ new Set();
|
|
331
|
+
const tasksByOutput = {};
|
|
332
|
+
for (const [taskName, taskConfig] of Object.entries(graphTasks)) {
|
|
333
|
+
const provides = getProvides(taskConfig);
|
|
334
|
+
provides.forEach((output) => {
|
|
335
|
+
allPossibleOutputs.add(output);
|
|
336
|
+
if (!tasksByOutput[output]) tasksByOutput[output] = [];
|
|
337
|
+
tasksByOutput[output].push(taskName);
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
for (const output of allPossibleOutputs) {
|
|
341
|
+
if (availableOutputs.includes(output)) continue;
|
|
342
|
+
const producers = tasksByOutput[output] ?? [];
|
|
343
|
+
const canStillProduce = producers.some((taskName) => {
|
|
344
|
+
const taskState = state.tasks[taskName];
|
|
345
|
+
if (taskState?.status === TASK_STATUS.COMPLETED || isNonActiveTask(taskState)) {
|
|
346
|
+
return false;
|
|
347
|
+
}
|
|
348
|
+
const taskConfig = graphTasks[taskName];
|
|
349
|
+
const requires = getRequires(taskConfig);
|
|
350
|
+
return requires.every((req) => availableOutputs.includes(req));
|
|
351
|
+
});
|
|
352
|
+
if (canStillProduce) {
|
|
353
|
+
return { isComplete: false, expectedCompletion: { taskNames: [], outputs: [] } };
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
const eligibleTasks = getEligibleCandidates(graph, state);
|
|
357
|
+
if (eligibleTasks.length > 0) {
|
|
358
|
+
return { isComplete: false, expectedCompletion: { taskNames: eligibleTasks, outputs: [] } };
|
|
359
|
+
}
|
|
360
|
+
const completedCount = Object.values(state.tasks).filter((t) => t.status === TASK_STATUS.COMPLETED).length;
|
|
361
|
+
return {
|
|
362
|
+
isComplete: completedCount > 0 || availableOutputs.length > 0,
|
|
363
|
+
expectedCompletion: { taskNames: [], outputs: [] }
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
function checkGoalReached(graph, state) {
|
|
367
|
+
const goal = graph.settings.goal ?? [];
|
|
368
|
+
if (goal.length === 0) {
|
|
369
|
+
return checkAllOutputsDone(graph, state);
|
|
370
|
+
}
|
|
371
|
+
const availableOutputs = computeAvailableOutputs(graph, state.tasks);
|
|
372
|
+
const goalReached = goal.every((output) => availableOutputs.includes(output));
|
|
373
|
+
return {
|
|
374
|
+
isComplete: goalReached,
|
|
375
|
+
expectedCompletion: { taskNames: [], outputs: goal }
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
function getEligibleCandidates(graph, state) {
|
|
379
|
+
const graphTasks = getAllTasks(graph);
|
|
380
|
+
const availableOutputs = computeAvailableOutputs(graph, state.tasks);
|
|
381
|
+
const candidates = [];
|
|
382
|
+
for (const [taskName, taskConfig] of Object.entries(graphTasks)) {
|
|
383
|
+
const taskState = state.tasks[taskName];
|
|
384
|
+
if (taskState?.status === TASK_STATUS.COMPLETED || taskState?.status === TASK_STATUS.RUNNING || isNonActiveTask(taskState)) {
|
|
385
|
+
continue;
|
|
386
|
+
}
|
|
387
|
+
const requires = getRequires(taskConfig);
|
|
388
|
+
if (requires.every((req) => availableOutputs.includes(req))) {
|
|
389
|
+
const provides = getProvides(taskConfig);
|
|
390
|
+
const allAlreadyAvailable = provides.length > 0 && provides.every((output) => availableOutputs.includes(output));
|
|
391
|
+
if (!allAlreadyAvailable) {
|
|
392
|
+
candidates.push(taskName);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
return candidates;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// src/event-graph/stuck-detection.ts
|
|
400
|
+
function detectStuckState(params) {
|
|
401
|
+
const { graph, state, eligibleTasks, completionResult } = params;
|
|
402
|
+
const tasks = state.tasks;
|
|
403
|
+
const graphTasks = getAllTasks(graph);
|
|
404
|
+
const availableOutputs = computeAvailableOutputs(graph, tasks);
|
|
405
|
+
if (eligibleTasks.length > 0) {
|
|
406
|
+
return { is_stuck: false, stuck_description: null, outputs_unresolvable: [], tasks_blocked: [] };
|
|
407
|
+
}
|
|
408
|
+
const hasRunningTasks = Object.values(tasks).some((t) => t.status === TASK_STATUS.RUNNING);
|
|
409
|
+
if (hasRunningTasks) {
|
|
410
|
+
return { is_stuck: false, stuck_description: null, outputs_unresolvable: [], tasks_blocked: [] };
|
|
411
|
+
}
|
|
412
|
+
if (completionResult?.expectedCompletion) {
|
|
413
|
+
const { taskNames = [], outputs = [] } = completionResult.expectedCompletion;
|
|
414
|
+
if (taskNames.length > 0) {
|
|
415
|
+
const expectedFailed = taskNames.filter((tn) => isNonActiveTask(tasks[tn]));
|
|
416
|
+
if (expectedFailed.length > 0 && expectedFailed.length === taskNames.length) {
|
|
417
|
+
return {
|
|
418
|
+
is_stuck: true,
|
|
419
|
+
stuck_description: `Completion expects tasks ${taskNames.join(", ")} but all are failed`,
|
|
420
|
+
tasks_blocked: expectedFailed,
|
|
421
|
+
outputs_unresolvable: outputs
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
if (outputs.length > 0 && state.executionConfig.completionStrategy !== "only-resolved") {
|
|
426
|
+
const missingOutputs2 = outputs.filter((o) => !availableOutputs.includes(o));
|
|
427
|
+
if (missingOutputs2.length > 0) {
|
|
428
|
+
const unprovidable = [];
|
|
429
|
+
for (const output of missingOutputs2) {
|
|
430
|
+
const providers = Object.entries(graphTasks).filter(([, config]) => getProvides(config).includes(output)).map(([name]) => name);
|
|
431
|
+
const viable = providers.filter((p) => !isNonActiveTask(tasks[p]));
|
|
432
|
+
if (viable.length === 0) {
|
|
433
|
+
unprovidable.push(output);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
if (unprovidable.length > 0) {
|
|
437
|
+
return {
|
|
438
|
+
is_stuck: true,
|
|
439
|
+
stuck_description: `Completion expects outputs '${unprovidable.join("', '")}' but no viable tasks can provide them`,
|
|
440
|
+
tasks_blocked: [],
|
|
441
|
+
outputs_unresolvable: unprovidable
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
const blockedTasks = [];
|
|
448
|
+
const missingOutputs = /* @__PURE__ */ new Set();
|
|
449
|
+
for (const [taskName, taskConfig] of Object.entries(graphTasks)) {
|
|
450
|
+
const taskState = tasks[taskName];
|
|
451
|
+
if (taskState?.status === TASK_STATUS.COMPLETED || isNonActiveTask(taskState) || taskState?.status === TASK_STATUS.RUNNING) {
|
|
452
|
+
continue;
|
|
453
|
+
}
|
|
454
|
+
const requires = getRequires(taskConfig);
|
|
455
|
+
const unmet = requires.filter((req) => !availableOutputs.includes(req));
|
|
456
|
+
if (unmet.length > 0) {
|
|
457
|
+
const canBeProvided = unmet.every((req) => {
|
|
458
|
+
const providers = Object.entries(graphTasks).filter(([, config]) => getProvides(config).includes(req)).map(([name]) => name);
|
|
459
|
+
return providers.some((p) => !isNonActiveTask(tasks[p]) && tasks[p]?.status !== TASK_STATUS.COMPLETED);
|
|
460
|
+
});
|
|
461
|
+
if (!canBeProvided) {
|
|
462
|
+
blockedTasks.push(taskName);
|
|
463
|
+
unmet.forEach((u) => missingOutputs.add(u));
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
if (blockedTasks.length > 0) {
|
|
468
|
+
return {
|
|
469
|
+
is_stuck: true,
|
|
470
|
+
stuck_description: `Tasks [${blockedTasks.join(", ")}] blocked by unresolvable dependencies: ${[...missingOutputs].join(", ")}`,
|
|
471
|
+
tasks_blocked: blockedTasks,
|
|
472
|
+
outputs_unresolvable: [...missingOutputs]
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
return { is_stuck: false, stuck_description: null, outputs_unresolvable: [], tasks_blocked: [] };
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// src/event-graph/scheduler.ts
|
|
479
|
+
function next(graph, state) {
|
|
480
|
+
const processingLog = [];
|
|
481
|
+
const graphTasks = getAllTasks(graph);
|
|
482
|
+
if (Object.keys(graphTasks).length === 0) {
|
|
483
|
+
return {
|
|
484
|
+
eligibleTasks: [],
|
|
485
|
+
isComplete: true,
|
|
486
|
+
stuckDetection: { is_stuck: false, stuck_description: null, outputs_unresolvable: [], tasks_blocked: [] },
|
|
487
|
+
hasConflicts: false,
|
|
488
|
+
conflicts: {},
|
|
489
|
+
strategy: state.executionConfig.conflictStrategy,
|
|
490
|
+
processingLog: ["No tasks defined"]
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
const mode = state.executionConfig.executionMode;
|
|
494
|
+
const conflictStrategy = state.executionConfig.conflictStrategy;
|
|
495
|
+
const candidates = getCandidateTasks(graph, state);
|
|
496
|
+
processingLog.push(`Found ${candidates.length} candidate tasks: ${candidates.join(", ") || "none"}`);
|
|
497
|
+
let eligible;
|
|
498
|
+
let hasConflicts = false;
|
|
499
|
+
let conflicts = {};
|
|
500
|
+
if (mode === "dependency-mode") {
|
|
501
|
+
eligible = candidates;
|
|
502
|
+
} else {
|
|
503
|
+
const selection = selectOptimalTasks(candidates, graph, state, conflictStrategy);
|
|
504
|
+
eligible = selection.eligibleTasks;
|
|
505
|
+
hasConflicts = selection.hasConflicts;
|
|
506
|
+
conflicts = selection.conflicts;
|
|
507
|
+
}
|
|
508
|
+
processingLog.push(`Eligible after conflict resolution: ${eligible.join(", ") || "none"}`);
|
|
509
|
+
const completionResult = isExecutionComplete(graph, state);
|
|
510
|
+
processingLog.push(`Execution complete: ${completionResult.isComplete}`);
|
|
511
|
+
const stuckDetection = detectStuckState({
|
|
512
|
+
graph,
|
|
513
|
+
state,
|
|
514
|
+
eligibleTasks: eligible,
|
|
515
|
+
completionResult
|
|
516
|
+
});
|
|
517
|
+
if (stuckDetection.is_stuck) {
|
|
518
|
+
processingLog.push(`STUCK: ${stuckDetection.stuck_description}`);
|
|
519
|
+
}
|
|
520
|
+
return {
|
|
521
|
+
eligibleTasks: eligible,
|
|
522
|
+
isComplete: completionResult.isComplete,
|
|
523
|
+
stuckDetection,
|
|
524
|
+
hasConflicts,
|
|
525
|
+
conflicts,
|
|
526
|
+
strategy: conflictStrategy,
|
|
527
|
+
processingLog
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
function getCandidateTasks(graph, state) {
|
|
531
|
+
const graphTasks = getAllTasks(graph);
|
|
532
|
+
const computedOutputs = computeAvailableOutputs(graph, state.tasks);
|
|
533
|
+
const availableOutputs = [.../* @__PURE__ */ new Set([...computedOutputs, ...state.availableOutputs])];
|
|
534
|
+
const candidates = [];
|
|
535
|
+
for (const [taskName, taskConfig] of Object.entries(graphTasks)) {
|
|
536
|
+
const taskState = state.tasks[taskName];
|
|
537
|
+
if (!isRepeatableTask(taskConfig)) {
|
|
538
|
+
if (taskState?.status === TASK_STATUS.COMPLETED || taskState?.status === TASK_STATUS.RUNNING || isNonActiveTask(taskState)) {
|
|
539
|
+
continue;
|
|
540
|
+
}
|
|
541
|
+
} else {
|
|
542
|
+
if (taskState?.status === TASK_STATUS.RUNNING || isNonActiveTask(taskState)) {
|
|
543
|
+
continue;
|
|
544
|
+
}
|
|
545
|
+
const maxExec = getRepeatableMax(taskConfig);
|
|
546
|
+
if (maxExec !== void 0 && taskState && taskState.executionCount >= maxExec) {
|
|
547
|
+
continue;
|
|
548
|
+
}
|
|
549
|
+
if (taskConfig.circuit_breaker) {
|
|
550
|
+
if (taskState && taskState.executionCount >= taskConfig.circuit_breaker.max_executions) {
|
|
551
|
+
continue;
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
if (taskState?.status === TASK_STATUS.COMPLETED) {
|
|
555
|
+
const requires2 = getRequires(taskConfig);
|
|
556
|
+
if (requires2.length > 0) {
|
|
557
|
+
const hasRefreshedInputs = requires2.some((req) => {
|
|
558
|
+
for (const [otherName, otherConfig] of Object.entries(graphTasks)) {
|
|
559
|
+
if (getProvides(otherConfig).includes(req)) {
|
|
560
|
+
const otherState = state.tasks[otherName];
|
|
561
|
+
if (otherState && otherState.executionCount > taskState.lastEpoch) {
|
|
562
|
+
return true;
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
return false;
|
|
567
|
+
});
|
|
568
|
+
if (!hasRefreshedInputs) continue;
|
|
569
|
+
} else {
|
|
570
|
+
continue;
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
const requires = getRequires(taskConfig);
|
|
575
|
+
if (!requires.every((req) => availableOutputs.includes(req))) {
|
|
576
|
+
continue;
|
|
577
|
+
}
|
|
578
|
+
if (!isRepeatableTask(taskConfig)) {
|
|
579
|
+
const provides = getProvides(taskConfig);
|
|
580
|
+
const allAlreadyAvailable = provides.length > 0 && provides.every((output) => availableOutputs.includes(output));
|
|
581
|
+
if (allAlreadyAvailable) continue;
|
|
582
|
+
}
|
|
583
|
+
candidates.push(taskName);
|
|
584
|
+
}
|
|
585
|
+
return candidates;
|
|
586
|
+
}
|
|
587
|
+
function selectOptimalTasks(candidates, graph, state, conflictStrategy) {
|
|
588
|
+
const result = { eligibleTasks: [], hasConflicts: false, conflicts: {} };
|
|
589
|
+
if (candidates.length === 0) return result;
|
|
590
|
+
const graphTasks = getAllTasks(graph);
|
|
591
|
+
switch (conflictStrategy) {
|
|
592
|
+
case "parallel-all":
|
|
593
|
+
result.eligibleTasks = candidates;
|
|
594
|
+
return result;
|
|
595
|
+
case "user-choice": {
|
|
596
|
+
result.eligibleTasks = candidates;
|
|
597
|
+
if (candidates.length > 1) {
|
|
598
|
+
const outputGroups2 = groupTasksByProvides(candidates, graphTasks);
|
|
599
|
+
for (const [outputKey, groupTasks] of Object.entries(outputGroups2)) {
|
|
600
|
+
if (groupTasks.length > 1) {
|
|
601
|
+
result.conflicts[outputKey] = groupTasks;
|
|
602
|
+
result.hasConflicts = true;
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
return result;
|
|
607
|
+
}
|
|
608
|
+
case "skip-conflicts":
|
|
609
|
+
result.eligibleTasks = getNonConflictingTasks(candidates, graphTasks);
|
|
610
|
+
return result;
|
|
611
|
+
case "random-select":
|
|
612
|
+
result.eligibleTasks = selectRandomTasks(candidates, graphTasks);
|
|
613
|
+
return result;
|
|
614
|
+
}
|
|
615
|
+
const outputGroups = groupTasksByProvides(candidates, graphTasks);
|
|
616
|
+
const runningOutputs = /* @__PURE__ */ new Set();
|
|
617
|
+
for (const [taskName, taskState] of Object.entries(state.tasks)) {
|
|
618
|
+
if (taskState.status === TASK_STATUS.RUNNING) {
|
|
619
|
+
const taskConfig = graph.tasks[taskName];
|
|
620
|
+
if (taskConfig) {
|
|
621
|
+
getProvides(taskConfig).forEach((o) => runningOutputs.add(o));
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
const selectedTasks = [];
|
|
626
|
+
const tasksInConflictGroups = /* @__PURE__ */ new Set();
|
|
627
|
+
for (const [outputKey, groupTasks] of Object.entries(outputGroups)) {
|
|
628
|
+
if (runningOutputs.has(outputKey)) continue;
|
|
629
|
+
if (groupTasks.length === 1) {
|
|
630
|
+
selectedTasks.push(groupTasks[0]);
|
|
631
|
+
} else {
|
|
632
|
+
const selected = selectBestAlternative(groupTasks, graphTasks, state, conflictStrategy);
|
|
633
|
+
selectedTasks.push(selected);
|
|
634
|
+
}
|
|
635
|
+
groupTasks.forEach((t) => tasksInConflictGroups.add(t));
|
|
636
|
+
}
|
|
637
|
+
const nonConflicting = candidates.filter((t) => !tasksInConflictGroups.has(t));
|
|
638
|
+
nonConflicting.forEach((t) => {
|
|
639
|
+
if (!selectedTasks.includes(t)) selectedTasks.push(t);
|
|
640
|
+
});
|
|
641
|
+
result.eligibleTasks = selectedTasks;
|
|
642
|
+
return result;
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
// src/event-graph/task-transitions.ts
|
|
646
|
+
function applyTaskStart(state, taskName) {
|
|
647
|
+
const existingTask = state.tasks[taskName] ?? createDefaultTaskState2();
|
|
648
|
+
const updatedTask = {
|
|
649
|
+
...existingTask,
|
|
650
|
+
status: "running",
|
|
651
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
652
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
653
|
+
progress: 0,
|
|
654
|
+
error: void 0
|
|
655
|
+
};
|
|
656
|
+
return {
|
|
657
|
+
...state,
|
|
658
|
+
tasks: { ...state.tasks, [taskName]: updatedTask },
|
|
659
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
|
|
660
|
+
};
|
|
661
|
+
}
|
|
662
|
+
function applyTaskCompletion(state, graph, taskName, result) {
|
|
663
|
+
const existingTask = state.tasks[taskName] ?? createDefaultTaskState2();
|
|
664
|
+
const taskConfig = graph.tasks[taskName];
|
|
665
|
+
if (!taskConfig) {
|
|
666
|
+
throw new Error(`Task "${taskName}" not found in graph`);
|
|
667
|
+
}
|
|
668
|
+
let outputTokens;
|
|
669
|
+
if (result && taskConfig.on && taskConfig.on[result]) {
|
|
670
|
+
outputTokens = taskConfig.on[result];
|
|
671
|
+
} else {
|
|
672
|
+
outputTokens = getProvides(taskConfig);
|
|
673
|
+
}
|
|
674
|
+
const updatedTask = {
|
|
675
|
+
...existingTask,
|
|
676
|
+
status: "completed",
|
|
677
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
678
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
679
|
+
executionCount: existingTask.executionCount + 1,
|
|
680
|
+
lastEpoch: existingTask.executionCount + 1,
|
|
681
|
+
error: void 0
|
|
682
|
+
};
|
|
683
|
+
if (isRepeatableTask(taskConfig)) {
|
|
684
|
+
updatedTask.status = "not-started";
|
|
685
|
+
}
|
|
686
|
+
const newOutputs = [.../* @__PURE__ */ new Set([...state.availableOutputs, ...outputTokens])];
|
|
687
|
+
return {
|
|
688
|
+
...state,
|
|
689
|
+
tasks: { ...state.tasks, [taskName]: updatedTask },
|
|
690
|
+
availableOutputs: newOutputs,
|
|
691
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
function applyTaskFailure(state, graph, taskName, error) {
|
|
695
|
+
const existingTask = state.tasks[taskName] ?? createDefaultTaskState2();
|
|
696
|
+
const taskConfig = graph.tasks[taskName];
|
|
697
|
+
if (taskConfig?.retry) {
|
|
698
|
+
const retryCount = existingTask.retryCount + 1;
|
|
699
|
+
if (retryCount <= taskConfig.retry.max_attempts) {
|
|
700
|
+
const updatedTask2 = {
|
|
701
|
+
...existingTask,
|
|
702
|
+
status: "not-started",
|
|
703
|
+
retryCount,
|
|
704
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
705
|
+
error
|
|
706
|
+
};
|
|
707
|
+
return {
|
|
708
|
+
...state,
|
|
709
|
+
tasks: { ...state.tasks, [taskName]: updatedTask2 },
|
|
710
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
|
|
711
|
+
};
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
const updatedTask = {
|
|
715
|
+
...existingTask,
|
|
716
|
+
status: "failed",
|
|
717
|
+
failedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
718
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
719
|
+
error,
|
|
720
|
+
executionCount: existingTask.executionCount + 1
|
|
721
|
+
};
|
|
722
|
+
let newOutputs = state.availableOutputs;
|
|
723
|
+
if (taskConfig?.on_failure && taskConfig.on_failure.length > 0) {
|
|
724
|
+
newOutputs = [.../* @__PURE__ */ new Set([...state.availableOutputs, ...taskConfig.on_failure])];
|
|
725
|
+
}
|
|
726
|
+
if (taskConfig?.circuit_breaker && updatedTask.executionCount >= taskConfig.circuit_breaker.max_executions) {
|
|
727
|
+
const breakTokens = taskConfig.circuit_breaker.on_break;
|
|
728
|
+
newOutputs = [.../* @__PURE__ */ new Set([...newOutputs, ...breakTokens])];
|
|
729
|
+
}
|
|
730
|
+
return {
|
|
731
|
+
...state,
|
|
732
|
+
tasks: { ...state.tasks, [taskName]: updatedTask },
|
|
733
|
+
availableOutputs: newOutputs,
|
|
734
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
|
|
735
|
+
};
|
|
736
|
+
}
|
|
737
|
+
function applyTaskProgress(state, taskName, message, progress) {
|
|
738
|
+
const existingTask = state.tasks[taskName] ?? createDefaultTaskState2();
|
|
739
|
+
const updatedTask = {
|
|
740
|
+
...existingTask,
|
|
741
|
+
progress: typeof progress === "number" ? progress : existingTask.progress,
|
|
742
|
+
messages: [
|
|
743
|
+
...existingTask.messages ?? [],
|
|
744
|
+
...message ? [{ message, timestamp: (/* @__PURE__ */ new Date()).toISOString(), status: existingTask.status }] : []
|
|
745
|
+
],
|
|
746
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
|
|
747
|
+
};
|
|
748
|
+
return {
|
|
749
|
+
...state,
|
|
750
|
+
tasks: { ...state.tasks, [taskName]: updatedTask },
|
|
751
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
|
|
752
|
+
};
|
|
753
|
+
}
|
|
754
|
+
function createDefaultTaskState2() {
|
|
755
|
+
return {
|
|
756
|
+
status: "not-started",
|
|
757
|
+
executionCount: 0,
|
|
758
|
+
retryCount: 0,
|
|
759
|
+
lastEpoch: 0,
|
|
760
|
+
messages: [],
|
|
761
|
+
progress: null
|
|
762
|
+
};
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
// src/event-graph/reducer.ts
|
|
766
|
+
function apply(state, event, graph) {
|
|
767
|
+
if ("executionId" in event && event.executionId && event.executionId !== state.executionId) {
|
|
768
|
+
return state;
|
|
769
|
+
}
|
|
770
|
+
switch (event.type) {
|
|
771
|
+
case "task-started":
|
|
772
|
+
return applyTaskStart(state, event.taskName);
|
|
773
|
+
case "task-completed":
|
|
774
|
+
return applyTaskCompletion(state, graph, event.taskName, event.result);
|
|
775
|
+
case "task-failed":
|
|
776
|
+
return applyTaskFailure(state, graph, event.taskName, event.error);
|
|
777
|
+
case "task-progress":
|
|
778
|
+
return applyTaskProgress(state, event.taskName, event.message, event.progress);
|
|
779
|
+
case "inject-tokens":
|
|
780
|
+
return applyInjectTokens(state, event.tokens);
|
|
781
|
+
case "agent-action":
|
|
782
|
+
return applyAgentAction(state, event.action, graph, event.config);
|
|
783
|
+
case "task-creation":
|
|
784
|
+
return applyTaskCreation(state, event.taskName, event.taskConfig);
|
|
785
|
+
default:
|
|
786
|
+
return state;
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
function applyAll(state, events, graph) {
|
|
790
|
+
return events.reduce((s, e) => apply(s, e, graph), state);
|
|
791
|
+
}
|
|
792
|
+
function applyInjectTokens(state, tokens) {
|
|
793
|
+
return {
|
|
794
|
+
...state,
|
|
795
|
+
availableOutputs: [.../* @__PURE__ */ new Set([...state.availableOutputs, ...tokens])],
|
|
796
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
|
|
797
|
+
};
|
|
798
|
+
}
|
|
799
|
+
function applyAgentAction(state, action, graph, config) {
|
|
800
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
801
|
+
switch (action) {
|
|
802
|
+
case "start": {
|
|
803
|
+
const executionId = `exec-${Date.now()}`;
|
|
804
|
+
const fresh = createInitialExecutionState(graph, executionId);
|
|
805
|
+
if (config) {
|
|
806
|
+
if (config.executionMode) {
|
|
807
|
+
fresh.executionConfig.executionMode = config.executionMode;
|
|
808
|
+
}
|
|
809
|
+
if (config.conflictStrategy) {
|
|
810
|
+
fresh.executionConfig.conflictStrategy = config.conflictStrategy;
|
|
811
|
+
}
|
|
812
|
+
if (config.completionStrategy) {
|
|
813
|
+
fresh.executionConfig.completionStrategy = config.completionStrategy;
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
return fresh;
|
|
817
|
+
}
|
|
818
|
+
case "stop":
|
|
819
|
+
return {
|
|
820
|
+
...state,
|
|
821
|
+
status: "stopped",
|
|
822
|
+
executionId: null,
|
|
823
|
+
lastUpdated: now
|
|
824
|
+
};
|
|
825
|
+
case "pause":
|
|
826
|
+
return {
|
|
827
|
+
...state,
|
|
828
|
+
status: "paused",
|
|
829
|
+
lastUpdated: now
|
|
830
|
+
};
|
|
831
|
+
case "resume":
|
|
832
|
+
return {
|
|
833
|
+
...state,
|
|
834
|
+
status: "running",
|
|
835
|
+
lastUpdated: now
|
|
836
|
+
};
|
|
837
|
+
default:
|
|
838
|
+
return state;
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
function applyTaskCreation(state, taskName, taskConfig) {
|
|
842
|
+
if (!taskName || !taskConfig || !Array.isArray(taskConfig.provides)) {
|
|
843
|
+
return state;
|
|
844
|
+
}
|
|
845
|
+
return {
|
|
846
|
+
...state,
|
|
847
|
+
tasks: {
|
|
848
|
+
...state.tasks,
|
|
849
|
+
[taskName]: createDefaultTaskState()
|
|
850
|
+
},
|
|
851
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
|
|
852
|
+
};
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
exports.COMPLETION_STRATEGIES = COMPLETION_STRATEGIES;
|
|
856
|
+
exports.CONFLICT_STRATEGIES = CONFLICT_STRATEGIES;
|
|
857
|
+
exports.DEFAULTS = DEFAULTS;
|
|
858
|
+
exports.EXECUTION_MODES = EXECUTION_MODES;
|
|
859
|
+
exports.EXECUTION_STATUS = EXECUTION_STATUS;
|
|
860
|
+
exports.TASK_STATUS = TASK_STATUS;
|
|
861
|
+
exports.addDynamicTask = addDynamicTask;
|
|
862
|
+
exports.addKeyToProvides = addKeyToProvides;
|
|
863
|
+
exports.addKeyToRequires = addKeyToRequires;
|
|
864
|
+
exports.apply = apply;
|
|
865
|
+
exports.applyAll = applyAll;
|
|
866
|
+
exports.applyTaskCompletion = applyTaskCompletion;
|
|
867
|
+
exports.applyTaskFailure = applyTaskFailure;
|
|
868
|
+
exports.applyTaskProgress = applyTaskProgress;
|
|
869
|
+
exports.applyTaskStart = applyTaskStart;
|
|
870
|
+
exports.computeAvailableOutputs = computeAvailableOutputs;
|
|
871
|
+
exports.createDefaultTaskState = createDefaultTaskState;
|
|
872
|
+
exports.createInitialExecutionState = createInitialExecutionState;
|
|
873
|
+
exports.detectStuckState = detectStuckState;
|
|
874
|
+
exports.getAllTasks = getAllTasks;
|
|
875
|
+
exports.getCandidateTasks = getCandidateTasks;
|
|
876
|
+
exports.getNonConflictingTasks = getNonConflictingTasks;
|
|
877
|
+
exports.getProvides = getProvides;
|
|
878
|
+
exports.getRepeatableMax = getRepeatableMax;
|
|
879
|
+
exports.getRequires = getRequires;
|
|
880
|
+
exports.getTask = getTask;
|
|
881
|
+
exports.groupTasksByProvides = groupTasksByProvides;
|
|
882
|
+
exports.hasOutputConflict = hasOutputConflict;
|
|
883
|
+
exports.hasTask = hasTask;
|
|
884
|
+
exports.isExecutionComplete = isExecutionComplete;
|
|
885
|
+
exports.isNonActiveTask = isNonActiveTask;
|
|
886
|
+
exports.isRepeatableTask = isRepeatableTask;
|
|
887
|
+
exports.isTaskCompleted = isTaskCompleted;
|
|
888
|
+
exports.isTaskRunning = isTaskRunning;
|
|
889
|
+
exports.next = next;
|
|
890
|
+
exports.removeKeyFromProvides = removeKeyFromProvides;
|
|
891
|
+
exports.removeKeyFromRequires = removeKeyFromRequires;
|
|
892
|
+
exports.selectBestAlternative = selectBestAlternative;
|
|
893
|
+
exports.selectRandomTasks = selectRandomTasks;
|
|
894
|
+
//# sourceMappingURL=index.cjs.map
|
|
895
|
+
//# sourceMappingURL=index.cjs.map
|