stageflow 0.2.0 → 0.8.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 +179 -14
- package/dist/agent/activity.d.ts +12 -1
- package/dist/agent/activity.js +37 -2
- package/dist/agent/activityObserver.d.ts +5 -1
- package/dist/agent/activityObserver.js +174 -11
- package/dist/agent/cursorProvider.d.ts +1 -10
- package/dist/agent/cursorProvider.js +18 -10
- package/dist/agent/fakeAgent.js +15 -7
- package/dist/agent/piAdapter.d.ts +18 -1
- package/dist/agent/piAdapter.js +115 -45
- package/dist/agent/port.d.ts +7 -0
- package/dist/agent/port.js +3 -0
- package/dist/agent/providerAuth.js +12 -7
- package/dist/catalog/displayCatalogPath.d.ts +12 -0
- package/dist/catalog/displayCatalogPath.js +28 -0
- package/dist/cli/artifactCommand.d.ts +10 -0
- package/dist/cli/artifactCommand.js +120 -0
- package/dist/cli/envelopeCommand.d.ts +32 -0
- package/dist/cli/envelopeCommand.js +285 -0
- package/dist/cli/exportRunCommand.d.ts +10 -0
- package/dist/cli/exportRunCommand.js +150 -0
- package/dist/cli/handoffFormat.d.ts +22 -0
- package/dist/cli/handoffFormat.js +61 -0
- package/dist/cli/initCommand.d.ts +9 -0
- package/dist/cli/initCommand.js +71 -0
- package/dist/cli/initTemplates.d.ts +3 -0
- package/dist/cli/initTemplates.js +19 -0
- package/dist/cli/operatorCatalog.d.ts +10 -0
- package/dist/cli/operatorCatalog.js +16 -0
- package/dist/cli/runCommand.d.ts +7 -1
- package/dist/cli/runCommand.js +83 -11
- package/dist/cli/runOutput.d.ts +4 -1
- package/dist/cli/runOutput.js +36 -8
- package/dist/cli/skillsCommand.d.ts +16 -0
- package/dist/cli/skillsCommand.js +459 -0
- package/dist/cli/validateCommand.d.ts +1 -1
- package/dist/cli/validateCommand.js +20 -3
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +128 -22
- package/dist/config/browseCatalog.d.ts +45 -0
- package/dist/config/browseCatalog.js +170 -0
- package/dist/config/createPipeline.d.ts +12 -3
- package/dist/config/createPipeline.js +292 -100
- package/dist/config/createStage.d.ts +10 -4
- package/dist/config/createStage.js +44 -14
- package/dist/config/listConfig.d.ts +14 -19
- package/dist/config/listConfig.js +26 -191
- package/dist/config/listModelsFromManifest.d.ts +2 -0
- package/dist/config/listModelsFromManifest.js +4 -0
- package/dist/config/loadOutcome.d.ts +4 -0
- package/dist/config/loadPipeline.d.ts +1 -15
- package/dist/config/loadPipeline.js +88 -142
- package/dist/config/loadStage.d.ts +4 -0
- package/dist/config/loadStage.js +60 -32
- package/dist/config/loadStageflowManifest.d.ts +5 -0
- package/dist/config/loadStageflowManifest.js +157 -0
- package/dist/config/mergePipelineIncludes.d.ts +9 -0
- package/dist/config/mergePipelineIncludes.js +141 -0
- package/dist/config/normalizePipelineStageEntry.d.ts +18 -0
- package/dist/config/normalizePipelineStageEntry.js +210 -0
- package/dist/config/pipelineStageKeys.d.ts +4 -0
- package/dist/config/pipelineStageKeys.js +14 -0
- package/dist/config/resolveCatalogContext.d.ts +13 -0
- package/dist/config/resolveCatalogContext.js +13 -0
- package/dist/config/resolveForkEmitContext.d.ts +4 -0
- package/dist/config/resolveForkEmitContext.js +34 -0
- package/dist/config/resolvePipelineDag.d.ts +5 -1
- package/dist/config/resolvePipelineDag.js +86 -36
- package/dist/config/scanCatalogPaths.d.ts +4 -0
- package/dist/config/scanCatalogPaths.js +83 -0
- package/dist/config/validateCatalog.d.ts +22 -4
- package/dist/config/validateCatalog.js +169 -132
- package/dist/envelope/check.d.ts +2 -0
- package/dist/envelope/check.js +58 -0
- package/dist/envelope/cloneForks.d.ts +2 -0
- package/dist/envelope/cloneForks.js +62 -0
- package/dist/envelope/forkChoice.d.ts +3 -0
- package/dist/envelope/forkChoice.js +47 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/mcp/catalogTools.d.ts +3 -0
- package/dist/mcp/catalogTools.js +187 -0
- package/dist/mcp/controlTools.d.ts +3 -0
- package/dist/mcp/controlTools.js +147 -0
- package/dist/mcp/deps.d.ts +11 -0
- package/dist/mcp/deps.js +1 -0
- package/dist/mcp/projectRun.d.ts +1 -37
- package/dist/mcp/projectRun.js +1 -57
- package/dist/mcp/resources.d.ts +5 -0
- package/dist/mcp/resources.js +45 -0
- package/dist/mcp/server.d.ts +16 -3
- package/dist/mcp/server.js +159 -3
- package/dist/mcp/toolResults.d.ts +7 -0
- package/dist/mcp/toolResults.js +6 -0
- package/dist/mcp/tools.d.ts +2 -7
- package/dist/mcp/tools.js +52 -86
- package/dist/mcp/waitRun.d.ts +46 -0
- package/dist/mcp/waitRun.js +146 -0
- package/dist/mcp/waitingGates.d.ts +12 -0
- package/dist/mcp/waitingGates.js +83 -0
- package/dist/project/findProjectRoot.d.ts +2 -0
- package/dist/project/findProjectRoot.js +51 -0
- package/dist/project/globalHome.d.ts +2 -0
- package/dist/project/globalHome.js +19 -0
- package/dist/project/resolveProjectContext.d.ts +9 -0
- package/dist/project/resolveProjectContext.js +38 -0
- package/dist/project/resolveStageflowContext.d.ts +11 -0
- package/dist/project/resolveStageflowContext.js +66 -0
- package/dist/projection/projectRun.d.ts +44 -0
- package/dist/projection/projectRun.js +71 -0
- package/dist/prompt/priorEnvelope.d.ts +1 -1
- package/dist/prompt/priorEnvelope.js +4 -1
- package/dist/runstore/normalizeCatalogPath.d.ts +1 -0
- package/dist/runstore/normalizeCatalogPath.js +4 -0
- package/dist/runstore/paths.js +2 -0
- package/dist/runstore/pipelineDagSnapshot.d.ts +9 -0
- package/dist/runstore/pipelineDagSnapshot.js +90 -1
- package/dist/runstore/port.d.ts +22 -2
- package/dist/runstore/port.js +4 -1
- package/dist/runstore/runProjection.d.ts +1 -1
- package/dist/runstore/runProjection.js +25 -4
- package/dist/runstore/sqlite/SqliteRunStore.d.ts +3 -2
- package/dist/runstore/sqlite/SqliteRunStore.js +65 -7
- package/dist/runstore/sqlite/schema.d.ts +1 -1
- package/dist/runstore/sqlite/schema.js +4 -1
- package/dist/runstore/stageInstanceId.d.ts +4 -0
- package/dist/runstore/stageInstanceId.js +23 -0
- package/dist/runstore/syntheticStageSnapshot.d.ts +1 -1
- package/dist/runstore/syntheticStageSnapshot.js +2 -1
- package/dist/runstore/trackProjection.js +28 -12
- package/dist/runstore/workspaceLayout.d.ts +1 -0
- package/dist/runstore/workspaceLayout.js +1 -1
- package/dist/runtime/cloneSchedule.d.ts +18 -0
- package/dist/runtime/cloneSchedule.js +233 -0
- package/dist/runtime/credentialBinding.d.ts +8 -6
- package/dist/runtime/credentialBinding.js +18 -24
- package/dist/runtime/envelopeRouting.d.ts +2 -1
- package/dist/runtime/envelopeRouting.js +80 -13
- package/dist/runtime/pipelineRunner.d.ts +3 -0
- package/dist/runtime/pipelineRunner.js +15 -1
- package/dist/runtime/pipelineScheduler.d.ts +8 -2
- package/dist/runtime/pipelineScheduler.js +215 -39
- package/dist/runtime/reloadRunCatalog.d.ts +5 -0
- package/dist/runtime/reloadRunCatalog.js +44 -0
- package/dist/runtime/resumeReconstruct.d.ts +1 -0
- package/dist/runtime/resumeReconstruct.js +31 -10
- package/dist/runtime/runChangeBus.d.ts +18 -0
- package/dist/runtime/runChangeBus.js +83 -0
- package/dist/runtime/runManager.d.ts +4 -0
- package/dist/runtime/runManager.js +36 -16
- package/dist/runtime/settingsFile.d.ts +12 -0
- package/dist/runtime/settingsFile.js +87 -6
- package/dist/runtime/stageAttemptBootstrap.d.ts +1 -0
- package/dist/runtime/stageAttemptBootstrap.js +18 -7
- package/dist/runtime/stageProcessLauncher.js +3 -0
- package/dist/runtime/stageRecovery.js +3 -1
- package/dist/runtime/stageRunner.d.ts +1 -0
- package/dist/runtime/stageRunner.js +17 -15
- package/dist/runtime/stageWorker.js +13 -10
- package/dist/server/bootstrap.d.ts +32 -0
- package/dist/server/bootstrap.js +56 -0
- package/dist/server/createHttpHost.d.ts +34 -0
- package/dist/server/createHttpHost.js +70 -0
- package/dist/server/http.d.ts +6 -13
- package/dist/server/http.js +297 -352
- package/dist/server/mcpHost.d.ts +22 -0
- package/dist/server/mcpHost.js +21 -0
- package/dist/server/operatorResults.d.ts +13 -0
- package/dist/server/operatorResults.js +22 -0
- package/dist/tools/emitStageEnvelope.d.ts +12 -1
- package/dist/tools/emitStageEnvelope.js +27 -1
- package/dist/types/envelope.d.ts +3 -0
- package/dist/types/forkChoice.d.ts +30 -0
- package/dist/types/forkChoice.js +1 -0
- package/dist/types/pipeline.d.ts +59 -2
- package/dist/types/stageflowManifest.d.ts +23 -0
- package/dist/types/stageflowManifest.js +1 -0
- package/dist/ui/assets/{index-DCsDopak.css → index-C3N7MXAC.css} +1 -1
- package/dist/ui/assets/index-CSoGDA3A.js +118 -0
- package/dist/ui/index.html +3 -2
- package/dist/ui/stageflow-icon.svg +12 -0
- package/package.json +8 -5
- package/skills/install-suite.sh +107 -0
- package/skills/stageflow/SKILL.md +26 -0
- package/skills/stageflow/references/control-surface.md +26 -0
- package/skills/stageflow/scripts/detect-host.mjs +54 -0
- package/skills/stageflow/scripts/detect-host.test.mjs +97 -0
- package/skills/stageflow-author/SKILL.md +58 -0
- package/skills/stageflow-author/assets/examples/branch-decision/hotfix.yaml +10 -0
- package/skills/stageflow-author/assets/examples/branch-decision/release-gate.pipeline.yaml +12 -0
- package/skills/stageflow-author/assets/examples/branch-decision/run-tests.yaml +13 -0
- package/skills/stageflow-author/assets/examples/branch-decision/ship.yaml +10 -0
- package/skills/stageflow-author/assets/examples/linear-review/draft.yaml +9 -0
- package/skills/stageflow-author/assets/examples/linear-review/publish.yaml +10 -0
- package/skills/stageflow-author/assets/examples/linear-review/review-loop.pipeline.yaml +10 -0
- package/skills/stageflow-author/assets/examples/linear-review/review.yaml +15 -0
- package/skills/stageflow-author/assets/examples/non-sdlc-digest/gather.yaml +9 -0
- package/skills/stageflow-author/assets/examples/non-sdlc-digest/research-digest.pipeline.yaml +10 -0
- package/skills/stageflow-author/assets/examples/non-sdlc-digest/send.yaml +10 -0
- package/skills/stageflow-author/assets/examples/non-sdlc-digest/summarize.yaml +9 -0
- package/skills/stageflow-author/references/catalog-mapping.md +131 -0
- package/skills/stageflow-author/references/catalog-write-conventions.md +29 -0
- package/skills/stageflow-author/references/stage-prompt-template.md +55 -0
- package/skills/stageflow-author/references/validate-and-report.md +38 -0
- package/skills/stageflow-delegate/SKILL.md +18 -0
- package/skills/stageflow-delegate/references/authoring-or-run.md +15 -0
- package/skills/stageflow-delegate/references/example-walkthrough.md +30 -0
- package/skills/stageflow-delegate/references/pattern-detection.md +44 -0
- package/skills/stageflow-run/SKILL.md +151 -0
- package/skills/stageflow-run/references/mcp-call.md +17 -0
- package/skills/stageflow-run/references/task-and-pipeline-selection.md +52 -0
- package/skills/stageflow-run/scripts/mcp-call.mjs +299 -0
- package/skills/stageflow-run/scripts/mcp-call.test.mjs +271 -0
- package/skills/stageflow-session-capture/SKILL.md +94 -0
- package/skills/stageflow-session-capture/assets/example-pipeline/example.pipeline.yaml +7 -0
- package/skills/stageflow-session-capture/assets/example-pipeline/implement.yaml +8 -0
- package/skills/stageflow-session-capture/assets/example-pipeline/research.yaml +8 -0
- package/skills/stageflow-session-capture/references/catalog-authoring.md +40 -0
- package/skills/stageflow-session-capture/references/transcript-sources.md +25 -0
- package/skills/stageflow-session-capture/scripts/check-provider-gate.mjs +43 -0
- package/skills/stageflow-session-capture/scripts/locate-session-transcript.mjs +141 -0
- package/skills/stageflow-session-capture/scripts/resolve-catalog-id.mjs +119 -0
- package/skills/stageflow-setup/SKILL.md +110 -0
- package/dist/ui/assets/index-Cry0Tpfx.js +0 -118
|
@@ -1,18 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
};
|
|
7
|
-
export type PipelineStageListing = {
|
|
8
|
-
id: string;
|
|
9
|
-
gate_kinds?: StageGateKind[];
|
|
10
|
-
};
|
|
11
|
-
export type PipelineListing = {
|
|
12
|
-
path: string;
|
|
13
|
-
id: string;
|
|
14
|
-
stages: PipelineStageListing[];
|
|
15
|
-
};
|
|
1
|
+
import type { StageGateKind } from "../types/stage.js";
|
|
2
|
+
import type { LoadedManifest } from "../types/stageflowManifest.js";
|
|
3
|
+
import { type PipelineListing, type TaskListing } from "./browseCatalog.js";
|
|
4
|
+
import { type StageflowContext } from "../project/resolveStageflowContext.js";
|
|
5
|
+
import { type CatalogContext } from "./resolveCatalogContext.js";
|
|
6
|
+
export type { PipelineListing, PipelineStageListing, TaskListing } from "./browseCatalog.js";
|
|
16
7
|
export type ValidStageListing = {
|
|
17
8
|
path: string;
|
|
18
9
|
id: string;
|
|
@@ -27,7 +18,11 @@ export type BrokenStageListing = {
|
|
|
27
18
|
gate_kinds?: StageGateKind[];
|
|
28
19
|
};
|
|
29
20
|
export type StageListing = ValidStageListing | BrokenStageListing;
|
|
30
|
-
export
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
21
|
+
export type CatalogListOptions = {
|
|
22
|
+
projectRoot: string;
|
|
23
|
+
manifest: LoadedManifest;
|
|
24
|
+
};
|
|
25
|
+
export declare function listTasks(options: CatalogListOptions): Promise<TaskListing[]>;
|
|
26
|
+
export declare function listPipelines(options: CatalogListOptions): Promise<PipelineListing[]>;
|
|
27
|
+
export declare function listStages(_options?: unknown): Promise<StageListing[]>;
|
|
28
|
+
export declare function listModels(cwdOrContext: string | CatalogContext | StageflowContext): Promise<string[]>;
|
|
@@ -1,195 +1,30 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
"cursor/auto",
|
|
12
|
-
"cursor/composer-2-5",
|
|
13
|
-
];
|
|
14
|
-
function parseSafeGateKinds(raw) {
|
|
15
|
-
if (!Array.isArray(raw) || !raw.every((item) => typeof item === "string")) {
|
|
16
|
-
return undefined;
|
|
17
|
-
}
|
|
18
|
-
const allowed = new Set(STAGE_GATE_KINDS);
|
|
19
|
-
const gateKinds = raw.filter((item) => allowed.has(item));
|
|
20
|
-
return gateKinds.length > 0 ? gateKinds : undefined;
|
|
1
|
+
import { listModelsForContext, listPipelinesForContext, listTasksForContext, } from "./browseCatalog.js";
|
|
2
|
+
import { resolveStageflowContext } from "../project/resolveStageflowContext.js";
|
|
3
|
+
import { catalogContextFromStageflow } from "./resolveCatalogContext.js";
|
|
4
|
+
export async function listTasks(options) {
|
|
5
|
+
return listTasksForContext({
|
|
6
|
+
projectRoot: options.projectRoot,
|
|
7
|
+
manifest: options.manifest,
|
|
8
|
+
manifestStatus: "ok",
|
|
9
|
+
issues: [],
|
|
10
|
+
});
|
|
21
11
|
}
|
|
22
|
-
async function
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
return new Map();
|
|
30
|
-
}
|
|
31
|
-
const usage = new Map();
|
|
32
|
-
for (const entry of entries) {
|
|
33
|
-
if (!entry.isFile() || !entry.name.endsWith(".yaml"))
|
|
34
|
-
continue;
|
|
35
|
-
const filePath = path.join(dir, entry.name);
|
|
36
|
-
try {
|
|
37
|
-
const raw = await readYamlObject(filePath);
|
|
38
|
-
if (typeof raw?.id !== "string" || !Array.isArray(raw.stages))
|
|
39
|
-
continue;
|
|
40
|
-
const stageIds = extractPipelineStageIds(raw.stages);
|
|
41
|
-
if (!stageIds)
|
|
42
|
-
continue;
|
|
43
|
-
for (const stageId of stageIds) {
|
|
44
|
-
let pipelineIds = usage.get(stageId);
|
|
45
|
-
if (!pipelineIds) {
|
|
46
|
-
pipelineIds = new Set();
|
|
47
|
-
usage.set(stageId, pipelineIds);
|
|
48
|
-
}
|
|
49
|
-
pipelineIds.add(raw.id);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
catch {
|
|
53
|
-
// skip invalid pipeline files
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
return usage;
|
|
12
|
+
export async function listPipelines(options) {
|
|
13
|
+
return listPipelinesForContext({
|
|
14
|
+
projectRoot: options.projectRoot,
|
|
15
|
+
manifest: options.manifest,
|
|
16
|
+
manifestStatus: "ok",
|
|
17
|
+
issues: [],
|
|
18
|
+
});
|
|
57
19
|
}
|
|
58
|
-
export async function
|
|
59
|
-
|
|
60
|
-
let entries;
|
|
61
|
-
try {
|
|
62
|
-
entries = await readdir(dir, { withFileTypes: true });
|
|
63
|
-
}
|
|
64
|
-
catch {
|
|
65
|
-
return [];
|
|
66
|
-
}
|
|
67
|
-
const listings = [];
|
|
68
|
-
for (const entry of entries) {
|
|
69
|
-
if (!entry.isFile() || !entry.name.endsWith(".yaml"))
|
|
70
|
-
continue;
|
|
71
|
-
const filePath = path.join(dir, entry.name);
|
|
72
|
-
try {
|
|
73
|
-
const task = await loadTask(filePath);
|
|
74
|
-
listings.push({
|
|
75
|
-
path: path.relative(cwd, filePath),
|
|
76
|
-
id: task.id,
|
|
77
|
-
goal: task.goal,
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
catch {
|
|
81
|
-
// skip invalid
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
listings.sort((a, b) => a.id.localeCompare(b.id));
|
|
85
|
-
return listings;
|
|
20
|
+
export async function listStages(_options) {
|
|
21
|
+
return [];
|
|
86
22
|
}
|
|
87
|
-
export async function
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
return [];
|
|
95
|
-
}
|
|
96
|
-
const listings = [];
|
|
97
|
-
for (const entry of entries) {
|
|
98
|
-
if (!entry.isFile() || !entry.name.endsWith(".yaml"))
|
|
99
|
-
continue;
|
|
100
|
-
const filePath = path.join(dir, entry.name);
|
|
101
|
-
try {
|
|
102
|
-
const loaded = await loadPipeline(filePath, { cwd });
|
|
103
|
-
listings.push({
|
|
104
|
-
path: path.relative(cwd, filePath),
|
|
105
|
-
id: loaded.pipeline.id,
|
|
106
|
-
stages: loaded.stages.map((stage) => ({
|
|
107
|
-
id: stage.id,
|
|
108
|
-
...(stage.gate_kinds ? { gate_kinds: stage.gate_kinds } : {}),
|
|
109
|
-
})),
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
catch {
|
|
113
|
-
// skip invalid
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
listings.sort((a, b) => a.id.localeCompare(b.id));
|
|
117
|
-
return listings;
|
|
118
|
-
}
|
|
119
|
-
export async function listStages(cwd) {
|
|
120
|
-
const dir = path.join(cwd, "stages");
|
|
121
|
-
let entries;
|
|
122
|
-
try {
|
|
123
|
-
entries = await readdir(dir, { withFileTypes: true });
|
|
124
|
-
}
|
|
125
|
-
catch {
|
|
126
|
-
return [];
|
|
127
|
-
}
|
|
128
|
-
const usageByStage = await listPipelineUsageByStage(cwd);
|
|
129
|
-
const valid = [];
|
|
130
|
-
const broken = [];
|
|
131
|
-
for (const entry of entries) {
|
|
132
|
-
if (!entry.isFile() || !entry.name.endsWith(".yaml"))
|
|
133
|
-
continue;
|
|
134
|
-
const filePath = path.join(dir, entry.name);
|
|
135
|
-
const relPath = path.relative(cwd, filePath);
|
|
136
|
-
try {
|
|
137
|
-
const stage = await loadStage(filePath);
|
|
138
|
-
valid.push({
|
|
139
|
-
path: relPath,
|
|
140
|
-
id: stage.id,
|
|
141
|
-
used_by_pipeline_ids: [...(usageByStage.get(stage.id) ?? new Set())].sort(),
|
|
142
|
-
...(stage.gate_kinds ? { gate_kinds: stage.gate_kinds } : {}),
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
catch (err) {
|
|
146
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
147
|
-
const brokenRow = {
|
|
148
|
-
path: relPath,
|
|
149
|
-
error: message,
|
|
150
|
-
};
|
|
151
|
-
try {
|
|
152
|
-
const raw = await readYamlObject(filePath);
|
|
153
|
-
if (typeof raw?.id === "string")
|
|
154
|
-
brokenRow.id = raw.id;
|
|
155
|
-
if (typeof raw?.model === "string")
|
|
156
|
-
brokenRow.model = raw.model;
|
|
157
|
-
const gateKinds = parseSafeGateKinds(raw?.gate_kinds);
|
|
158
|
-
if (gateKinds)
|
|
159
|
-
brokenRow.gate_kinds = gateKinds;
|
|
160
|
-
}
|
|
161
|
-
catch {
|
|
162
|
-
// keep path + error only when parsing itself fails
|
|
163
|
-
}
|
|
164
|
-
broken.push(brokenRow);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
valid.sort((a, b) => a.id.localeCompare(b.id));
|
|
168
|
-
broken.sort((a, b) => a.path.localeCompare(b.path));
|
|
169
|
-
return [...valid, ...broken];
|
|
170
|
-
}
|
|
171
|
-
export async function listModels(cwd) {
|
|
172
|
-
const dir = path.join(cwd, "stages");
|
|
173
|
-
const models = new Set(BAKED_MODEL_IDS);
|
|
174
|
-
let entries;
|
|
175
|
-
try {
|
|
176
|
-
entries = await readdir(dir, { withFileTypes: true });
|
|
177
|
-
}
|
|
178
|
-
catch {
|
|
179
|
-
return [...models].sort((a, b) => a.localeCompare(b));
|
|
180
|
-
}
|
|
181
|
-
for (const entry of entries) {
|
|
182
|
-
if (!entry.isFile() || !entry.name.endsWith(".yaml"))
|
|
183
|
-
continue;
|
|
184
|
-
try {
|
|
185
|
-
const raw = await readYamlObject(path.join(dir, entry.name));
|
|
186
|
-
if (typeof raw?.model === "string" && raw.model.trim()) {
|
|
187
|
-
models.add(raw.model);
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
catch {
|
|
191
|
-
// ignore unreadable or invalid stage YAML
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
return [...models].sort((a, b) => a.localeCompare(b));
|
|
23
|
+
export async function listModels(cwdOrContext) {
|
|
24
|
+
const ctx = typeof cwdOrContext === "string"
|
|
25
|
+
? catalogContextFromStageflow(await resolveStageflowContext(cwdOrContext))
|
|
26
|
+
: "manifestIssues" in cwdOrContext
|
|
27
|
+
? catalogContextFromStageflow(cwdOrContext)
|
|
28
|
+
: cwdOrContext;
|
|
29
|
+
return listModelsForContext(ctx);
|
|
195
30
|
}
|
|
@@ -1,25 +1,11 @@
|
|
|
1
1
|
import type { LoadedPipeline } from "../types/pipeline.js";
|
|
2
2
|
import { type LoadOutcome } from "./loadOutcome.js";
|
|
3
|
-
import type { ValidationFinding } from "./validateCatalog.js";
|
|
4
3
|
export type { LoadedPipeline } from "../types/pipeline.js";
|
|
5
4
|
export type { LoadIssue, LoadOutcome } from "./loadOutcome.js";
|
|
6
|
-
export
|
|
7
|
-
ok: true;
|
|
8
|
-
loaded: LoadedPipeline;
|
|
9
|
-
} | {
|
|
10
|
-
ok: false;
|
|
11
|
-
findings: ValidationFinding[];
|
|
12
|
-
};
|
|
5
|
+
export declare function resolvePipelinePath(pipelinePath: string, cwd: string): Promise<string>;
|
|
13
6
|
export declare function loadPipelineOutcome(nameOrPath: string, options?: {
|
|
14
7
|
cwd?: string;
|
|
15
|
-
stagesDir?: string;
|
|
16
8
|
}): Promise<LoadOutcome<LoadedPipeline>>;
|
|
17
|
-
export declare function loadPipelineValidated(nameOrPath: string, options?: {
|
|
18
|
-
cwd?: string;
|
|
19
|
-
stagesDir?: string;
|
|
20
|
-
validateStages?: boolean;
|
|
21
|
-
}): Promise<LoadPipelineValidatedResult>;
|
|
22
9
|
export declare function loadPipeline(nameOrPath: string, options?: {
|
|
23
10
|
cwd?: string;
|
|
24
|
-
stagesDir?: string;
|
|
25
11
|
}): Promise<LoadedPipeline>;
|
|
@@ -1,68 +1,38 @@
|
|
|
1
1
|
import { access } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { loadFailure, loadSuccess } from "./loadOutcome.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
async function resolvePipelinePath(
|
|
9
|
-
const
|
|
4
|
+
import { mergePipelineStages } from "./mergePipelineIncludes.js";
|
|
5
|
+
import { normalizePipelineStageEntries, toWiringRefs, } from "./normalizePipelineStageEntry.js";
|
|
6
|
+
import { loadStageFromObjectOutcome, loadStageOutcome } from "./loadStage.js";
|
|
7
|
+
import { resolvePipelineDagFromRefs } from "./resolvePipelineDag.js";
|
|
8
|
+
export async function resolvePipelinePath(pipelinePath, cwd) {
|
|
9
|
+
const resolved = path.normalize(path.resolve(cwd, pipelinePath));
|
|
10
10
|
try {
|
|
11
|
-
await access(
|
|
12
|
-
return
|
|
11
|
+
await access(resolved);
|
|
12
|
+
return resolved;
|
|
13
13
|
}
|
|
14
14
|
catch {
|
|
15
|
-
|
|
16
|
-
await access(candidate);
|
|
17
|
-
return candidate;
|
|
15
|
+
throw new Error(`Pipeline file not found: ${resolved}. Pass a filesystem path to --pipeline (e.g. pipelines/hello.pipeline.yaml), not a bare pipeline id.`);
|
|
18
16
|
}
|
|
19
17
|
}
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
},
|
|
35
|
-
]);
|
|
36
|
-
}
|
|
37
|
-
let raw;
|
|
38
|
-
try {
|
|
39
|
-
raw = await readYamlObject(pipelinePath);
|
|
40
|
-
}
|
|
41
|
-
catch (err) {
|
|
42
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
43
|
-
return loadFailure([
|
|
44
|
-
{
|
|
45
|
-
code: "pipeline.load_error",
|
|
46
|
-
message,
|
|
47
|
-
category: "pipeline",
|
|
48
|
-
},
|
|
49
|
-
]);
|
|
50
|
-
}
|
|
51
|
-
if (typeof raw?.id !== "string" || !Array.isArray(raw.stages)) {
|
|
52
|
-
return loadFailure([
|
|
53
|
-
{
|
|
54
|
-
code: "pipeline.invalid_shape",
|
|
55
|
-
message: `Invalid pipeline ${pipelinePath}: id and stages[] are required`,
|
|
56
|
-
category: "pipeline",
|
|
57
|
-
},
|
|
58
|
-
]);
|
|
59
|
-
}
|
|
60
|
-
const pipelineId = raw.id;
|
|
61
|
-
const ctx = { pipelineId: raw.id, path: pipelinePath };
|
|
18
|
+
async function loadPipelineFromPath(pipelinePath) {
|
|
19
|
+
const normalizedPipelinePath = path.normalize(path.resolve(pipelinePath));
|
|
20
|
+
const mergeOutcome = await mergePipelineStages(normalizedPipelinePath);
|
|
21
|
+
if (!mergeOutcome.ok) {
|
|
22
|
+
return loadFailure(mergeOutcome.issues);
|
|
23
|
+
}
|
|
24
|
+
const { entries: rawEntries, pipelineId } = mergeOutcome.value;
|
|
25
|
+
const ctx = { pipelineId, path: normalizedPipelinePath };
|
|
26
|
+
const normalizeOutcome = normalizePipelineStageEntries(rawEntries, ctx);
|
|
27
|
+
if (!normalizeOutcome.ok) {
|
|
28
|
+
return loadFailure(normalizeOutcome.issues);
|
|
29
|
+
}
|
|
30
|
+
const normalizedEntries = normalizeOutcome.value;
|
|
31
|
+
const wiringRefs = toWiringRefs(normalizedEntries);
|
|
62
32
|
let stageIds;
|
|
63
33
|
let dag;
|
|
64
34
|
try {
|
|
65
|
-
const resolved =
|
|
35
|
+
const resolved = resolvePipelineDagFromRefs(wiringRefs, ctx);
|
|
66
36
|
stageIds = resolved.stages;
|
|
67
37
|
dag = resolved.dag;
|
|
68
38
|
}
|
|
@@ -77,115 +47,91 @@ export async function loadPipelineOutcome(nameOrPath, options = {}) {
|
|
|
77
47
|
},
|
|
78
48
|
]);
|
|
79
49
|
}
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
stages: stageIds,
|
|
83
|
-
};
|
|
50
|
+
const entryById = new Map(normalizedEntries.map((entry) => [entry.id, entry]));
|
|
51
|
+
const stageSources = {};
|
|
84
52
|
const stages = [];
|
|
85
|
-
for (const stageId of
|
|
86
|
-
const
|
|
87
|
-
|
|
53
|
+
for (const stageId of stageIds) {
|
|
54
|
+
const entry = entryById.get(stageId);
|
|
55
|
+
if (!entry) {
|
|
56
|
+
return loadFailure([
|
|
57
|
+
{
|
|
58
|
+
code: "pipeline.invalid_shape",
|
|
59
|
+
message: `Pipeline ${pipelineId}: missing normalized entry for stage "${stageId}"`,
|
|
60
|
+
category: "pipeline",
|
|
61
|
+
pipelineId,
|
|
62
|
+
},
|
|
63
|
+
]);
|
|
64
|
+
}
|
|
65
|
+
if (entry.body.kind === "inline") {
|
|
66
|
+
const inlineOutcome = loadStageFromObjectOutcome(entry.body.raw, {
|
|
67
|
+
entryId: entry.id,
|
|
68
|
+
declaringPath: entry.declaringPath,
|
|
69
|
+
});
|
|
70
|
+
if (!inlineOutcome.ok) {
|
|
71
|
+
return loadFailure(inlineOutcome.issues);
|
|
72
|
+
}
|
|
73
|
+
stages.push(inlineOutcome.value);
|
|
74
|
+
stageSources[stageId] = { kind: "inline" };
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
const stageOutcome = await loadStageOutcome(entry.body.absolutePath);
|
|
88
78
|
if (!stageOutcome.ok) {
|
|
89
|
-
const message = `Pipeline ${pipeline.id} references missing stage "${stageId}" at ${stagePath}`;
|
|
90
79
|
return loadFailure([
|
|
91
80
|
{
|
|
92
81
|
code: "pipeline.missing_stage",
|
|
93
|
-
message
|
|
82
|
+
message: `Pipeline ${pipelineId} references missing stage "${stageId}" at ${entry.body.absolutePath}`,
|
|
94
83
|
category: "pipeline",
|
|
95
84
|
pipelineId,
|
|
96
85
|
},
|
|
86
|
+
...stageOutcome.issues,
|
|
97
87
|
]);
|
|
98
88
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
return findingStageIdFilenameMismatch(cwd, stagePath, fileStem, raw.id);
|
|
89
|
+
if (stageOutcome.value.id !== entry.id) {
|
|
90
|
+
return loadFailure([
|
|
91
|
+
{
|
|
92
|
+
code: "pipeline.stage_id_mismatch",
|
|
93
|
+
message: `Pipeline ${pipelineId}: stage entry "${entry.id}" in ${entry.declaringPath} uses ${entry.body.path} which declares id "${stageOutcome.value.id}"`,
|
|
94
|
+
category: "pipeline",
|
|
95
|
+
pipelineId,
|
|
96
|
+
},
|
|
97
|
+
]);
|
|
109
98
|
}
|
|
99
|
+
const stage = {
|
|
100
|
+
...stageOutcome.value,
|
|
101
|
+
...(entry.skill !== undefined ? { skill: entry.skill } : {}),
|
|
102
|
+
};
|
|
103
|
+
stages.push(stage);
|
|
104
|
+
stageSources[stageId] = { kind: "file", path: entry.body.absolutePath };
|
|
110
105
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
if (!outcome.ok) {
|
|
123
|
-
findings.push(...findingsFromLoadIssues(cwd, stagePath, outcome.issues));
|
|
124
|
-
return findings;
|
|
125
|
-
}
|
|
126
|
-
if (!mismatch && path.basename(stagePath, ".yaml") !== outcome.value.id) {
|
|
127
|
-
findings.push(findingStageIdFilenameMismatch(cwd, stagePath, path.basename(stagePath, ".yaml"), outcome.value.id));
|
|
128
|
-
}
|
|
129
|
-
return findings;
|
|
106
|
+
const pipeline = {
|
|
107
|
+
id: pipelineId,
|
|
108
|
+
stages: stageIds,
|
|
109
|
+
};
|
|
110
|
+
return loadSuccess({
|
|
111
|
+
pipeline,
|
|
112
|
+
stages,
|
|
113
|
+
dag,
|
|
114
|
+
pipelinePath: normalizedPipelinePath,
|
|
115
|
+
stageSources,
|
|
116
|
+
});
|
|
130
117
|
}
|
|
131
|
-
export async function
|
|
118
|
+
export async function loadPipelineOutcome(nameOrPath, options = {}) {
|
|
132
119
|
const cwd = options.cwd ?? process.cwd();
|
|
133
|
-
const stagesDir = options.stagesDir ?? path.join(cwd, "stages");
|
|
134
|
-
const validateStages = options.validateStages ?? true;
|
|
135
120
|
let pipelinePath;
|
|
136
121
|
try {
|
|
137
122
|
pipelinePath = await resolvePipelinePath(nameOrPath, cwd);
|
|
138
123
|
}
|
|
139
124
|
catch (err) {
|
|
140
125
|
const message = err instanceof Error ? err.message : String(err);
|
|
141
|
-
return
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
},
|
|
149
|
-
]),
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
const referencedStageIds = new Set();
|
|
153
|
-
try {
|
|
154
|
-
const raw = await readYamlObject(pipelinePath);
|
|
155
|
-
if (typeof raw?.id === "string" && Array.isArray(raw.stages)) {
|
|
156
|
-
const stageIds = extractPipelineStageIds(raw.stages);
|
|
157
|
-
if (stageIds) {
|
|
158
|
-
for (const stageId of stageIds) {
|
|
159
|
-
referencedStageIds.add(stageId);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
catch {
|
|
165
|
-
// loadPipelineOutcome will report read errors
|
|
166
|
-
}
|
|
167
|
-
const outcome = await loadPipelineOutcome(nameOrPath, { cwd, stagesDir });
|
|
168
|
-
const findings = [];
|
|
169
|
-
if (!outcome.ok) {
|
|
170
|
-
findings.push(...findingsFromLoadIssues(cwd, pipelinePath, outcome.issues));
|
|
171
|
-
if (validateStages) {
|
|
172
|
-
for (const stageId of referencedStageIds) {
|
|
173
|
-
const stagePath = path.join(stagesDir, `${stageId}.yaml`);
|
|
174
|
-
findings.push(...(await validateStageFile(cwd, stagePath)));
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
return { ok: false, findings };
|
|
178
|
-
}
|
|
179
|
-
if (validateStages) {
|
|
180
|
-
for (const stageId of outcome.value.pipeline.stages) {
|
|
181
|
-
const stagePath = path.join(stagesDir, `${stageId}.yaml`);
|
|
182
|
-
findings.push(...(await validateStageFile(cwd, stagePath)));
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
if (findings.some((finding) => finding.severity === "error")) {
|
|
186
|
-
return { ok: false, findings };
|
|
126
|
+
return loadFailure([
|
|
127
|
+
{
|
|
128
|
+
code: "pipeline.load_error",
|
|
129
|
+
message,
|
|
130
|
+
category: "pipeline",
|
|
131
|
+
},
|
|
132
|
+
]);
|
|
187
133
|
}
|
|
188
|
-
return
|
|
134
|
+
return loadPipelineFromPath(pipelinePath);
|
|
189
135
|
}
|
|
190
136
|
export async function loadPipeline(nameOrPath, options = {}) {
|
|
191
137
|
const outcome = await loadPipelineOutcome(nameOrPath, options);
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { type StageConfig } from "../types/stage.js";
|
|
2
2
|
import { type LoadOutcome } from "./loadOutcome.js";
|
|
3
|
+
export declare function loadStageFromObjectOutcome(raw: Record<string, unknown>, ctx: {
|
|
4
|
+
entryId: string;
|
|
5
|
+
declaringPath: string;
|
|
6
|
+
}): LoadOutcome<StageConfig>;
|
|
3
7
|
export declare function loadStageOutcome(filePath: string): Promise<LoadOutcome<StageConfig>>;
|
|
4
8
|
export declare function loadStage(filePath: string): Promise<StageConfig>;
|