@elsium-ai/workflows 0.3.0 → 0.4.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/dist/dag.d.ts +4 -0
- package/dist/dag.d.ts.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +118 -0
- package/dist/types.d.ts +10 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/dag.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dag.d.ts","sourceRoot":"","sources":["../src/dag.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEX,iBAAiB,EAKjB,MAAM,SAAS,CAAA;AAChB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAkJ1C,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,iBAAiB,GAAG,QAAQ,CA+BrE"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { step, executeStep } from './step';
|
|
2
2
|
export { defineWorkflow, defineParallelWorkflow, defineBranchWorkflow } from './workflow';
|
|
3
3
|
export type { Workflow, ParallelWorkflowConfig, BranchConfig } from './workflow';
|
|
4
|
-
export
|
|
4
|
+
export { defineDagWorkflow } from './dag';
|
|
5
|
+
export type { StepConfig, StepContext, StepResult, StepStatus, RetryConfig, WorkflowConfig, WorkflowResult, WorkflowStatus, WorkflowRunOptions, DagStepConfig, DagWorkflowConfig, } from './types';
|
|
5
6
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAA;AAG1C,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AACzF,YAAY,EAAE,QAAQ,EAAE,sBAAsB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAGhF,YAAY,EACX,UAAU,EACV,WAAW,EACX,UAAU,EACV,UAAU,EACV,WAAW,EACX,cAAc,EACd,cAAc,EACd,cAAc,EACd,kBAAkB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAA;AAG1C,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AACzF,YAAY,EAAE,QAAQ,EAAE,sBAAsB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAGhF,OAAO,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAA;AAGzC,YAAY,EACX,UAAU,EACV,WAAW,EACX,UAAU,EACV,UAAU,EACV,WAAW,EACX,cAAc,EACd,cAAc,EACd,cAAc,EACd,kBAAkB,EAClB,aAAa,EACb,iBAAiB,GACjB,MAAM,SAAS,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -372,10 +372,128 @@ function defineBranchWorkflow(name, branches, fallback) {
|
|
|
372
372
|
}
|
|
373
373
|
};
|
|
374
374
|
}
|
|
375
|
+
// src/dag.ts
|
|
376
|
+
function buildDependencyMaps(steps) {
|
|
377
|
+
const stepMap = new Map(steps.map((s) => [s.name, s]));
|
|
378
|
+
const inDegree = new Map;
|
|
379
|
+
const dependents = new Map;
|
|
380
|
+
for (const step2 of steps) {
|
|
381
|
+
inDegree.set(step2.name, 0);
|
|
382
|
+
dependents.set(step2.name, []);
|
|
383
|
+
}
|
|
384
|
+
for (const step2 of steps) {
|
|
385
|
+
validateAndRegisterDeps(step2, stepMap, inDegree, dependents);
|
|
386
|
+
}
|
|
387
|
+
return { inDegree, dependents };
|
|
388
|
+
}
|
|
389
|
+
function validateAndRegisterDeps(step2, stepMap, inDegree, dependents) {
|
|
390
|
+
for (const dep of step2.dependsOn ?? []) {
|
|
391
|
+
if (!stepMap.has(dep)) {
|
|
392
|
+
throw new Error(`Step "${step2.name}" depends on unknown step "${dep}"`);
|
|
393
|
+
}
|
|
394
|
+
inDegree.set(step2.name, (inDegree.get(step2.name) ?? 0) + 1);
|
|
395
|
+
dependents.get(dep)?.push(step2.name);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
function findNextWave(inDegree, resolved, steps) {
|
|
399
|
+
const wave = [];
|
|
400
|
+
for (const [name, degree] of inDegree) {
|
|
401
|
+
if (degree === 0 && !resolved.has(name)) {
|
|
402
|
+
wave.push(name);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
if (wave.length === 0) {
|
|
406
|
+
const remaining = steps.filter((s) => !resolved.has(s.name)).map((s) => s.name);
|
|
407
|
+
throw new Error(`Cycle detected in DAG workflow. Remaining steps: ${remaining.join(", ")}`);
|
|
408
|
+
}
|
|
409
|
+
return wave;
|
|
410
|
+
}
|
|
411
|
+
function resolveWave(wave, resolved, inDegree, dependents) {
|
|
412
|
+
for (const name of wave) {
|
|
413
|
+
resolved.add(name);
|
|
414
|
+
for (const dep of dependents.get(name) ?? []) {
|
|
415
|
+
inDegree.set(dep, (inDegree.get(dep) ?? 0) - 1);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
function topologicalSort(steps) {
|
|
420
|
+
const { inDegree, dependents } = buildDependencyMaps(steps);
|
|
421
|
+
const waves = [];
|
|
422
|
+
const resolved = new Set;
|
|
423
|
+
while (resolved.size < steps.length) {
|
|
424
|
+
const wave = findNextWave(inDegree, resolved, steps);
|
|
425
|
+
resolveWave(wave, resolved, inDegree, dependents);
|
|
426
|
+
waves.push(wave);
|
|
427
|
+
}
|
|
428
|
+
return waves;
|
|
429
|
+
}
|
|
430
|
+
function resolveStepInput(stepConfig, outputs, input) {
|
|
431
|
+
const deps = stepConfig.dependsOn ?? [];
|
|
432
|
+
return deps.length > 0 ? outputs[deps[0]] ?? input : input;
|
|
433
|
+
}
|
|
434
|
+
function executeWaveSteps(wave, stepMap, config, input, outputs, options) {
|
|
435
|
+
const wavePromises = wave.map((stepName) => stepMap.get(stepName)).filter((s) => s !== undefined).map((stepConfig) => {
|
|
436
|
+
const stepInput = resolveStepInput(stepConfig, outputs, input);
|
|
437
|
+
const context = {
|
|
438
|
+
workflowName: config.name,
|
|
439
|
+
stepIndex: config.steps.indexOf(stepConfig),
|
|
440
|
+
previousOutputs: { ...outputs },
|
|
441
|
+
signal: options?.signal
|
|
442
|
+
};
|
|
443
|
+
return executeStep(stepConfig, stepInput, context);
|
|
444
|
+
});
|
|
445
|
+
return Promise.all(wavePromises);
|
|
446
|
+
}
|
|
447
|
+
async function processWaveResults(waveResults, wave, stepResults, outputs, config) {
|
|
448
|
+
let failed = false;
|
|
449
|
+
for (let i = 0;i < waveResults.length; i++) {
|
|
450
|
+
const result = waveResults[i];
|
|
451
|
+
const stepName = wave[i];
|
|
452
|
+
stepResults.push(result);
|
|
453
|
+
if (result.status === "completed" && result.data !== undefined) {
|
|
454
|
+
outputs[stepName] = result.data;
|
|
455
|
+
}
|
|
456
|
+
await config.onStepComplete?.(result);
|
|
457
|
+
if (result.status === "failed") {
|
|
458
|
+
failed = true;
|
|
459
|
+
await config.onStepError?.(new Error(result.error ?? "Step failed"), stepName);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
return failed;
|
|
463
|
+
}
|
|
464
|
+
function defineDagWorkflow(config) {
|
|
465
|
+
const stepMap = new Map(config.steps.map((s) => [s.name, s]));
|
|
466
|
+
return {
|
|
467
|
+
name: config.name,
|
|
468
|
+
async run(input, options) {
|
|
469
|
+
const startTime = performance.now();
|
|
470
|
+
const waves = topologicalSort(config.steps);
|
|
471
|
+
const stepResults = [];
|
|
472
|
+
const outputs = {};
|
|
473
|
+
let failed = false;
|
|
474
|
+
for (const wave of waves) {
|
|
475
|
+
const waveResults = await executeWaveSteps(wave, stepMap, config, input, outputs, options);
|
|
476
|
+
failed = await processWaveResults(waveResults, wave, stepResults, outputs, config);
|
|
477
|
+
if (failed)
|
|
478
|
+
break;
|
|
479
|
+
}
|
|
480
|
+
const workflowResult = {
|
|
481
|
+
name: config.name,
|
|
482
|
+
status: failed ? "failed" : "completed",
|
|
483
|
+
steps: stepResults,
|
|
484
|
+
totalDurationMs: Math.round(performance.now() - startTime),
|
|
485
|
+
outputs
|
|
486
|
+
};
|
|
487
|
+
await config.onComplete?.(workflowResult);
|
|
488
|
+
return workflowResult;
|
|
489
|
+
}
|
|
490
|
+
};
|
|
491
|
+
}
|
|
375
492
|
export {
|
|
376
493
|
step,
|
|
377
494
|
executeStep,
|
|
378
495
|
defineWorkflow,
|
|
379
496
|
defineParallelWorkflow,
|
|
497
|
+
defineDagWorkflow,
|
|
380
498
|
defineBranchWorkflow
|
|
381
499
|
};
|
package/dist/types.d.ts
CHANGED
|
@@ -47,4 +47,14 @@ export interface WorkflowResult {
|
|
|
47
47
|
export interface WorkflowRunOptions {
|
|
48
48
|
signal?: AbortSignal;
|
|
49
49
|
}
|
|
50
|
+
export interface DagStepConfig<TInput = unknown, TOutput = unknown> extends StepConfig<TInput, TOutput> {
|
|
51
|
+
dependsOn?: string[];
|
|
52
|
+
}
|
|
53
|
+
export interface DagWorkflowConfig {
|
|
54
|
+
name: string;
|
|
55
|
+
steps: DagStepConfig[];
|
|
56
|
+
onStepComplete?: (result: StepResult) => void | Promise<void>;
|
|
57
|
+
onStepError?: (error: Error, stepName: string) => void | Promise<void>;
|
|
58
|
+
onComplete?: (result: WorkflowResult) => void | Promise<void>;
|
|
59
|
+
}
|
|
50
60
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAI5B,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAA;AAEnF,MAAM,WAAW,UAAU,CAAC,MAAM,GAAG,OAAO,EAAE,OAAO,GAAG,OAAO;IAC9D,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IACzB,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IAClE,KAAK,CAAC,EAAE,WAAW,CAAA;IACnB,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,KAAK,OAAO,CAAA;IAC5D,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,WAAW;IAC3B,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACxC,MAAM,CAAC,EAAE,WAAW,CAAA;CACpB;AAED,MAAM,WAAW,UAAU,CAAC,CAAC,GAAG,OAAO;IACtC,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,UAAU,CAAA;IAClB,IAAI,CAAC,EAAE,CAAC,CAAA;IACR,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;CAClB;AAID,MAAM,WAAW,WAAW;IAC3B,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAA;CACvC;AAID,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAA;AAE3E,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,UAAU,EAAE,CAAA;IACnB,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC7D,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACtE,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC7D;AAED,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,cAAc,CAAA;IACtB,KAAK,EAAE,UAAU,EAAE,CAAA;IACnB,eAAe,EAAE,MAAM,CAAA;IACvB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAChC;AAED,MAAM,WAAW,kBAAkB;IAClC,MAAM,CAAC,EAAE,WAAW,CAAA;CACpB"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elsium-ai/workflows",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Multi-step workflow pipelines and DAG execution for ElsiumAI",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Eric Utrera <ebutrera9103@gmail.com>",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"dev": "bun --watch src/index.ts"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@elsium-ai/core": "^0.
|
|
29
|
+
"@elsium-ai/core": "^0.4.1",
|
|
30
30
|
"zod": "^3.24.0"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|