@cascade-flow/runner 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -2
- package/dist/discovery.d.ts +1 -0
- package/dist/discovery.d.ts.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +148 -20
- package/dist/index.js.map +8 -7
- package/dist/subprocess-executor.d.ts +1 -1
- package/dist/subprocess-executor.d.ts.map +1 -1
- package/dist/types.d.ts +5 -66
- package/dist/types.d.ts.map +1 -1
- package/dist/versioning.d.ts +29 -0
- package/dist/versioning.d.ts.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -76,8 +76,13 @@ workflows/my-workflow/
|
|
|
76
76
|
├── input-schema.ts # Optional: Zod schema
|
|
77
77
|
├── defineStep.ts # Optional: Typed helper
|
|
78
78
|
└── steps/
|
|
79
|
-
├── step-1/step.ts
|
|
80
|
-
|
|
79
|
+
├── step-1/step.ts # Flat step
|
|
80
|
+
├── step-2/step.ts # Flat step
|
|
81
|
+
└── data-processing/ # Optional: Group directory
|
|
82
|
+
├── extract/
|
|
83
|
+
│ └── fetch-data/step.ts # Nested step
|
|
84
|
+
└── transform/
|
|
85
|
+
└── normalize/step.ts # Nested step
|
|
81
86
|
```
|
|
82
87
|
|
|
83
88
|
## Key Features
|
|
@@ -87,6 +92,7 @@ workflows/my-workflow/
|
|
|
87
92
|
- **Cycle detection** - DFS validation prevents circular dependencies
|
|
88
93
|
- **Resume capability** - Continue from previous runs
|
|
89
94
|
- **Pluggable backend** - Abstract persistence layer
|
|
95
|
+
- **Nested step groups** - Organize steps in arbitrary directory hierarchies (purely organizational)
|
|
90
96
|
|
|
91
97
|
## Exports
|
|
92
98
|
|
package/dist/discovery.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export declare function loadWorkflowConfig(workflowDir: string): Promise<Workflo
|
|
|
17
17
|
export declare function discoverWorkflows(workflowsRoot?: string): Promise<LocalWorkflowMetadata[]>;
|
|
18
18
|
/**
|
|
19
19
|
* Discovers and loads all steps from a directory
|
|
20
|
+
* Supports arbitrary deep nesting of steps in group subdirectories
|
|
20
21
|
*
|
|
21
22
|
* @param root - Root directory containing step subdirectories (defaults to "./steps")
|
|
22
23
|
* @returns Array of loaded steps with wired dependencies
|
package/dist/discovery.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"AAMA,OAAO,EAA0C,KAAK,UAAU,EAAyB,KAAK,cAAc,EAAE,KAAK,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAG1J;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,cAAc,CAAC,CA0BzB;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,aAAa,SAA4B,GACxC,OAAO,CAAC,qBAAqB,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"AAMA,OAAO,EAA0C,KAAK,UAAU,EAAyB,KAAK,cAAc,EAAE,KAAK,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAG1J;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,cAAc,CAAC,CA0BzB;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,aAAa,SAA4B,GACxC,OAAO,CAAC,qBAAqB,EAAE,CAAC,CA+ElC;AA4CD;;;;;;GAMG;AACH,wBAAsB,aAAa,CACjC,IAAI,SAAwB,GAC3B,OAAO,CAAC,UAAU,EAAE,CAAC,CAkFvB"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Backend, LogEntry } from "@cascade-flow/backend-interface";
|
|
2
|
-
import type { StepOutput,
|
|
2
|
+
import type { StepOutput, RunnerContext } from "@cascade-flow/workflow";
|
|
3
|
+
import type { LoadedStep } from "./types";
|
|
3
4
|
export type { LoadedStep };
|
|
4
5
|
/**
|
|
5
6
|
* Execute a step in an isolated child process
|
|
@@ -22,4 +23,5 @@ export declare function runAll(options: {
|
|
|
22
23
|
input?: unknown;
|
|
23
24
|
}): Promise<Record<string, StepOutput>>;
|
|
24
25
|
export { discoverWorkflows, discoverSteps } from "./discovery";
|
|
26
|
+
export { calculateWorkflowHash, getGitInfo } from "./versioning";
|
|
25
27
|
//# 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":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAa,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAMpF,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAa,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAMpF,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACxE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAI1C,YAAY,EAAE,UAAU,EAAE,CAAC;AAE3B;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrC,GAAG,EAAE,aAAa,EAClB,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,OAAO,EAChB,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EAC/C,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,WAAW,CAAA;CAAE,GACjC,OAAO,CAAC;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,QAAQ,EAAE,CAAA;CAAE,CAAC,CAoBnD;AAED,wBAAsB,MAAM,CAAC,OAAO,EAAE;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;IAC7B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;CACnB,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAkctC;AAGD,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG/D,OAAO,EAAE,qBAAqB,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ var __export = (target, all) => {
|
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
// src/index.ts
|
|
13
|
-
import { join } from "node:path";
|
|
13
|
+
import { join as join2 } from "node:path";
|
|
14
14
|
|
|
15
15
|
// src/discovery.ts
|
|
16
16
|
import fs from "node:fs/promises";
|
|
@@ -12532,7 +12532,11 @@ async function discoverWorkflows(workflowsRoot = path.resolve("workflows")) {
|
|
|
12532
12532
|
if (schemaMod?.inputSchema) {
|
|
12533
12533
|
inputSchema = schemaMod.inputSchema;
|
|
12534
12534
|
}
|
|
12535
|
-
} catch {
|
|
12535
|
+
} catch (error46) {
|
|
12536
|
+
if (error46?.code === "ENOENT" || error46?.code === "ERR_MODULE_NOT_FOUND") {} else {
|
|
12537
|
+
throw new Error(`Failed to load input schema at ${inputSchemaPath}: ${error46?.message || error46}`);
|
|
12538
|
+
}
|
|
12539
|
+
}
|
|
12536
12540
|
workflows.push({
|
|
12537
12541
|
slug: entry.name,
|
|
12538
12542
|
name: config2.name,
|
|
@@ -12547,18 +12551,32 @@ async function discoverWorkflows(workflowsRoot = path.resolve("workflows")) {
|
|
|
12547
12551
|
}
|
|
12548
12552
|
return workflows;
|
|
12549
12553
|
}
|
|
12550
|
-
async function
|
|
12554
|
+
async function discoverStepDirectories(root, relativePath = "") {
|
|
12551
12555
|
const entries = await fs.readdir(root, { withFileTypes: true });
|
|
12552
|
-
const
|
|
12553
|
-
const
|
|
12554
|
-
|
|
12555
|
-
|
|
12556
|
-
|
|
12556
|
+
const results = [];
|
|
12557
|
+
for (const entry of entries) {
|
|
12558
|
+
if (!entry.isDirectory()) {
|
|
12559
|
+
continue;
|
|
12560
|
+
}
|
|
12561
|
+
const fullPath = path.join(root, entry.name);
|
|
12562
|
+
const stepFile = path.join(fullPath, "step.ts");
|
|
12563
|
+
const currentPath = relativePath ? `${relativePath}/${entry.name}` : entry.name;
|
|
12557
12564
|
try {
|
|
12558
12565
|
await fs.access(stepFile);
|
|
12566
|
+
results.push({ dir: fullPath, stepId: currentPath });
|
|
12559
12567
|
} catch {
|
|
12560
|
-
|
|
12568
|
+
const nestedSteps = await discoverStepDirectories(fullPath, currentPath);
|
|
12569
|
+
results.push(...nestedSteps);
|
|
12561
12570
|
}
|
|
12571
|
+
}
|
|
12572
|
+
return results;
|
|
12573
|
+
}
|
|
12574
|
+
async function discoverSteps(root = path.resolve("steps")) {
|
|
12575
|
+
const stepDirs = await discoverStepDirectories(root);
|
|
12576
|
+
const loaded = [];
|
|
12577
|
+
const byModuleStepObject = new Map;
|
|
12578
|
+
for (const { dir, stepId } of stepDirs) {
|
|
12579
|
+
const stepFile = path.join(dir, "step.ts");
|
|
12562
12580
|
const modUrl = pathToFileURL(stepFile).toString();
|
|
12563
12581
|
const mod = await import(modUrl);
|
|
12564
12582
|
if (!mod?.step || typeof mod.step.fn !== "function") {
|
|
@@ -12569,10 +12587,9 @@ async function discoverSteps(root = path.resolve("steps")) {
|
|
|
12569
12587
|
const errors3 = validationResult.error.issues.map((e) => `${e.path.join(".")}: ${e.message}`).join(", ");
|
|
12570
12588
|
throw new Error(`Invalid step configuration at ${stepFile}: ${errors3}`);
|
|
12571
12589
|
}
|
|
12572
|
-
const dirName = path.basename(dir);
|
|
12573
12590
|
const placeholder = {
|
|
12574
|
-
id:
|
|
12575
|
-
name: mod.step.name ??
|
|
12591
|
+
id: stepId,
|
|
12592
|
+
name: mod.step.name ?? stepId.split("/").pop(),
|
|
12576
12593
|
dir,
|
|
12577
12594
|
fn: mod.step.fn,
|
|
12578
12595
|
exportOutput: mod.step.exportOutput,
|
|
@@ -12635,11 +12652,10 @@ import { spawn } from "node:child_process";
|
|
|
12635
12652
|
import { resolve, dirname } from "node:path";
|
|
12636
12653
|
import { fileURLToPath } from "node:url";
|
|
12637
12654
|
import { mkdir, readFile, unlink } from "node:fs/promises";
|
|
12638
|
-
import { getMicrosecondTimestamp } from "@cascade-flow/backend-interface";
|
|
12655
|
+
import { getMicrosecondTimestamp, ensureErrorMessage } from "@cascade-flow/backend-interface";
|
|
12639
12656
|
function createStreamHandler(streamType, attemptNumber, emitLog) {
|
|
12640
12657
|
let buffer = "";
|
|
12641
12658
|
const handler = (chunk) => {
|
|
12642
|
-
const timestamp = getMicrosecondTimestamp();
|
|
12643
12659
|
buffer += chunk.toString();
|
|
12644
12660
|
const lines = buffer.split(`
|
|
12645
12661
|
`);
|
|
@@ -12647,6 +12663,7 @@ function createStreamHandler(streamType, attemptNumber, emitLog) {
|
|
|
12647
12663
|
for (const line of lines) {
|
|
12648
12664
|
if (!line.trim())
|
|
12649
12665
|
continue;
|
|
12666
|
+
const timestamp = getMicrosecondTimestamp();
|
|
12650
12667
|
emitLog({
|
|
12651
12668
|
timestamp,
|
|
12652
12669
|
stream: streamType,
|
|
@@ -12670,7 +12687,7 @@ function createStreamHandler(streamType, attemptNumber, emitLog) {
|
|
|
12670
12687
|
return { handler, getBuffer, flushBuffer };
|
|
12671
12688
|
}
|
|
12672
12689
|
async function executeStepInSubprocess(stepFile, stepId, dependencies, ctx, attemptNumber, outputPath, onLog, options) {
|
|
12673
|
-
const executorPath = resolve(dirname(fileURLToPath(import.meta.url)), "step-executor
|
|
12690
|
+
const executorPath = resolve(dirname(fileURLToPath(import.meta.url)), "step-executor");
|
|
12674
12691
|
await mkdir(dirname(outputPath), { recursive: true });
|
|
12675
12692
|
return new Promise((resolve2, reject) => {
|
|
12676
12693
|
const child = spawn("bun", [executorPath], {
|
|
@@ -12762,7 +12779,8 @@ async function executeStepInSubprocess(stepFile, stepId, dependencies, ctx, atte
|
|
|
12762
12779
|
if (lastStderrLog) {
|
|
12763
12780
|
try {
|
|
12764
12781
|
const errorObj = JSON.parse(lastStderrLog.message);
|
|
12765
|
-
const
|
|
12782
|
+
const errorMessage = ensureErrorMessage(errorObj.message);
|
|
12783
|
+
const error46 = new Error(errorMessage);
|
|
12766
12784
|
error46.stack = errorObj.stack;
|
|
12767
12785
|
error46.name = errorObj.name || "Error";
|
|
12768
12786
|
reject(error46);
|
|
@@ -12785,6 +12803,87 @@ async function executeStepInSubprocess(stepFile, stepId, dependencies, ctx, atte
|
|
|
12785
12803
|
// src/index.ts
|
|
12786
12804
|
import { getMicrosecondTimestamp as getMicrosecondTimestamp2 } from "@cascade-flow/backend-interface";
|
|
12787
12805
|
import { Skip, isOptional as isOptional2 } from "@cascade-flow/workflow";
|
|
12806
|
+
|
|
12807
|
+
// src/versioning.ts
|
|
12808
|
+
import { createHash } from "node:crypto";
|
|
12809
|
+
import { readFile as readFile2, readdir } from "node:fs/promises";
|
|
12810
|
+
import { join } from "node:path";
|
|
12811
|
+
import { exec } from "node:child_process";
|
|
12812
|
+
import { promisify } from "node:util";
|
|
12813
|
+
var execAsync = promisify(exec);
|
|
12814
|
+
async function calculateWorkflowHash(workflow) {
|
|
12815
|
+
const hash2 = createHash("sha256");
|
|
12816
|
+
try {
|
|
12817
|
+
const workflowJsonPath = join(workflow.dir, "workflow.json");
|
|
12818
|
+
const workflowJsonContent = await readFile2(workflowJsonPath, "utf-8");
|
|
12819
|
+
hash2.update(`workflow.json:${workflowJsonContent}`);
|
|
12820
|
+
} catch (error46) {
|
|
12821
|
+
throw new Error(`Failed to read workflow.json for ${workflow.slug}: ${error46 instanceof Error ? error46.message : "Unknown error"}`);
|
|
12822
|
+
}
|
|
12823
|
+
try {
|
|
12824
|
+
const inputSchemaPath = join(workflow.dir, "input-schema.ts");
|
|
12825
|
+
const inputSchemaContent = await readFile2(inputSchemaPath, "utf-8");
|
|
12826
|
+
hash2.update(`input-schema.ts:${inputSchemaContent}`);
|
|
12827
|
+
} catch (error46) {
|
|
12828
|
+
if (error46 && typeof error46 === "object" && "code" in error46 && error46.code !== "ENOENT") {
|
|
12829
|
+
throw error46;
|
|
12830
|
+
}
|
|
12831
|
+
}
|
|
12832
|
+
const stepFiles = await collectStepFiles(workflow.stepsDir);
|
|
12833
|
+
stepFiles.sort();
|
|
12834
|
+
for (const stepFilePath of stepFiles) {
|
|
12835
|
+
try {
|
|
12836
|
+
const content = await readFile2(stepFilePath, "utf-8");
|
|
12837
|
+
const relativePath = stepFilePath.replace(workflow.stepsDir + "/", "");
|
|
12838
|
+
hash2.update(`step:${relativePath}:${content}`);
|
|
12839
|
+
} catch (error46) {
|
|
12840
|
+
throw new Error(`Failed to read step file ${stepFilePath}: ${error46 instanceof Error ? error46.message : "Unknown error"}`);
|
|
12841
|
+
}
|
|
12842
|
+
}
|
|
12843
|
+
const digest = hash2.digest("hex");
|
|
12844
|
+
return `sha256:${digest}`;
|
|
12845
|
+
}
|
|
12846
|
+
async function collectStepFiles(stepsDir) {
|
|
12847
|
+
const files = [];
|
|
12848
|
+
async function scan(dir) {
|
|
12849
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
12850
|
+
for (const entry of entries) {
|
|
12851
|
+
const fullPath = join(dir, entry.name);
|
|
12852
|
+
if (entry.isDirectory()) {
|
|
12853
|
+
await scan(fullPath);
|
|
12854
|
+
} else if (entry.isFile() && entry.name === "step.ts") {
|
|
12855
|
+
files.push(fullPath);
|
|
12856
|
+
}
|
|
12857
|
+
}
|
|
12858
|
+
}
|
|
12859
|
+
try {
|
|
12860
|
+
await scan(stepsDir);
|
|
12861
|
+
} catch (error46) {
|
|
12862
|
+
throw new Error(`Failed to scan steps directory ${stepsDir}: ${error46 instanceof Error ? error46.message : "Unknown error"}`);
|
|
12863
|
+
}
|
|
12864
|
+
return files;
|
|
12865
|
+
}
|
|
12866
|
+
async function getGitInfo(workflowDir) {
|
|
12867
|
+
try {
|
|
12868
|
+
const { stdout: commit } = await execAsync("git rev-parse HEAD", {
|
|
12869
|
+
cwd: workflowDir
|
|
12870
|
+
});
|
|
12871
|
+
const { stdout: branch } = await execAsync("git rev-parse --abbrev-ref HEAD", { cwd: workflowDir });
|
|
12872
|
+
const { stdout: status } = await execAsync("git status --porcelain", {
|
|
12873
|
+
cwd: workflowDir
|
|
12874
|
+
});
|
|
12875
|
+
const dirty = status.trim().length > 0;
|
|
12876
|
+
return {
|
|
12877
|
+
commit: commit.trim(),
|
|
12878
|
+
branch: branch.trim(),
|
|
12879
|
+
dirty
|
|
12880
|
+
};
|
|
12881
|
+
} catch (error46) {
|
|
12882
|
+
return;
|
|
12883
|
+
}
|
|
12884
|
+
}
|
|
12885
|
+
|
|
12886
|
+
// src/index.ts
|
|
12788
12887
|
async function executeStepInProcess(stepFile, stepId, dependencies, ctx, attemptNumber, backend, onLog, options) {
|
|
12789
12888
|
const outputPath = backend.getStepOutputPath(ctx.workflow.slug, ctx.runId, stepId, attemptNumber);
|
|
12790
12889
|
return executeStepInSubprocess(stepFile, stepId, dependencies, ctx, attemptNumber, outputPath, onLog, options);
|
|
@@ -12825,9 +12924,21 @@ async function runAll(options) {
|
|
|
12825
12924
|
};
|
|
12826
12925
|
const workflowStartTime = getMicrosecondTimestamp2();
|
|
12827
12926
|
await backend.initializeRun(workflowSlug, runId);
|
|
12927
|
+
const versionId = await calculateWorkflowHash(workflow);
|
|
12928
|
+
const git = await getGitInfo(workflow.dir);
|
|
12929
|
+
const stepManifest = steps.map((s) => s.id);
|
|
12930
|
+
await backend.createWorkflowVersion({
|
|
12931
|
+
workflowSlug,
|
|
12932
|
+
versionId,
|
|
12933
|
+
createdAt: getMicrosecondTimestamp2(),
|
|
12934
|
+
stepManifest,
|
|
12935
|
+
totalSteps: steps.length,
|
|
12936
|
+
git
|
|
12937
|
+
});
|
|
12828
12938
|
const hasInputSchema = workflow.inputSchema !== undefined;
|
|
12829
12939
|
const hasInput = options.input !== undefined;
|
|
12830
12940
|
await backend.saveWorkflowStart(workflowSlug, runId, {
|
|
12941
|
+
versionId,
|
|
12831
12942
|
workflowAttemptNumber: 1,
|
|
12832
12943
|
hasInputSchema,
|
|
12833
12944
|
hasInput
|
|
@@ -12876,10 +12987,25 @@ ${errorMessage}`
|
|
|
12876
12987
|
}
|
|
12877
12988
|
if (options?.resume) {
|
|
12878
12989
|
defaultCtx.log(`Resuming run ${defaultCtx.runId}...`);
|
|
12990
|
+
const workflowEvents = await backend.loadEvents(workflowSlug, defaultCtx.runId, { category: "workflow" });
|
|
12991
|
+
const workflowStartedEvent = workflowEvents.find((e) => e.type === "WorkflowStarted");
|
|
12992
|
+
if (workflowStartedEvent && workflowStartedEvent.type === "WorkflowStarted") {
|
|
12993
|
+
const previousVersionId = workflowStartedEvent.versionId;
|
|
12994
|
+
if (previousVersionId !== versionId) {
|
|
12995
|
+
const previousVersion = await backend.getWorkflowVersion(workflowSlug, previousVersionId);
|
|
12996
|
+
const currentVersion = await backend.getWorkflowVersion(workflowSlug, versionId);
|
|
12997
|
+
defaultCtx.log(`⚠️ Workflow definition changed since original run`);
|
|
12998
|
+
defaultCtx.log(` Original: ${previousVersionId}`);
|
|
12999
|
+
defaultCtx.log(` Current: ${versionId}`);
|
|
13000
|
+
if (previousVersion?.git && currentVersion?.git) {
|
|
13001
|
+
defaultCtx.log(` Git: ${previousVersion.git.commit} → ${currentVersion.git.commit}`);
|
|
13002
|
+
}
|
|
13003
|
+
}
|
|
13004
|
+
}
|
|
12879
13005
|
const existingRecords = await backend.loadRun(workflowSlug, defaultCtx.runId);
|
|
12880
13006
|
let resumedSteps = 0;
|
|
12881
13007
|
for (const record2 of existingRecords) {
|
|
12882
|
-
if (record2.status === "completed" && record2.output) {
|
|
13008
|
+
if (record2.status === "completed" && record2.output !== undefined && record2.output !== null) {
|
|
12883
13009
|
try {
|
|
12884
13010
|
const output = JSON.parse(record2.output);
|
|
12885
13011
|
cache.set(record2.stepId, Promise.resolve(output));
|
|
@@ -12941,7 +13067,7 @@ ${errorMessage}`
|
|
|
12941
13067
|
defaultCtx.log(`⊘ ${step.name} (skipped: dependency '${cascadedFromStep.name}' was skipped)`);
|
|
12942
13068
|
return {};
|
|
12943
13069
|
}
|
|
12944
|
-
const stepFile =
|
|
13070
|
+
const stepFile = join2(step.dir, "step.ts");
|
|
12945
13071
|
const maxRetries = step.maxRetries ?? 0;
|
|
12946
13072
|
let lastError = null;
|
|
12947
13073
|
for (let attemptNumber = 1;attemptNumber <= maxRetries + 1; attemptNumber++) {
|
|
@@ -13077,9 +13203,11 @@ ${errorMessage}`
|
|
|
13077
13203
|
}
|
|
13078
13204
|
export {
|
|
13079
13205
|
runAll,
|
|
13206
|
+
getGitInfo,
|
|
13080
13207
|
executeStepInProcess,
|
|
13081
13208
|
discoverWorkflows,
|
|
13082
|
-
discoverSteps
|
|
13209
|
+
discoverSteps,
|
|
13210
|
+
calculateWorkflowHash
|
|
13083
13211
|
};
|
|
13084
13212
|
|
|
13085
|
-
//# debugId=
|
|
13213
|
+
//# debugId=0A6F5DFCD4D7954F64756E2164756E21
|