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
package/dist/cli.js
CHANGED
|
@@ -4,34 +4,61 @@ import { realpathSync } from "node:fs";
|
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { PiAgentAdapter } from "./agent/piAdapter.js";
|
|
7
|
+
import { ARTIFACT_USAGE, runArtifactCommand } from "./cli/artifactCommand.js";
|
|
8
|
+
import { ENVELOPE_USAGE, runEnvelopeCommand, } from "./cli/envelopeCommand.js";
|
|
9
|
+
import { EXPORT_RUN_USAGE, runExportRunCommand, } from "./cli/exportRunCommand.js";
|
|
10
|
+
import { INIT_USAGE, runInitCommand } from "./cli/initCommand.js";
|
|
7
11
|
import { PROVIDERS_USAGE, runProvidersCommand } from "./cli/providersCommand.js";
|
|
8
12
|
import { RUN_USAGE, runRunCommand } from "./cli/runCommand.js";
|
|
13
|
+
import { resolveOperatorCatalog } from "./cli/operatorCatalog.js";
|
|
14
|
+
import { SKILLS_USAGE, runSkillsCommand } from "./cli/skillsCommand.js";
|
|
9
15
|
import { VALIDATE_USAGE, runValidateCommand } from "./cli/validateCommand.js";
|
|
10
16
|
import { createRunStore } from "./runstore/createStore.js";
|
|
17
|
+
import { resolveStageflowContext } from "./project/resolveStageflowContext.js";
|
|
11
18
|
import { exitForOutcome, runStageWorker } from "./runtime/stageWorker.js";
|
|
12
19
|
import { SF_STAGE_WORKER } from "./runtime/stageWorkerProtocol.js";
|
|
13
20
|
import { DEFAULT_PORT, startUiServer } from "./server/http.js";
|
|
21
|
+
import { startMcpServer } from "./server/mcpHost.js";
|
|
22
|
+
import { resolveMcpStateless } from "./mcp/server.js";
|
|
14
23
|
const USAGE = `Usage:
|
|
15
|
-
sf
|
|
16
|
-
sf
|
|
17
|
-
sf
|
|
24
|
+
sf init
|
|
25
|
+
sf run --task <path> --pipeline <path> [--checkout <path>] [--json] [--include stages] [--skip-gates] [--git-sha <sha>] [--ci-pr-url <url>] [--ci-job-url <url>] [--operator-cwd <path>] [--operator-agent-dir <path>]
|
|
26
|
+
sf validate [--pipeline <path>] [--task <path>] [--strict] [--json]
|
|
27
|
+
sf artifact read --run <runId> --path <relPath> [--out <file>]
|
|
28
|
+
sf envelope get --run <runId> --stage <stageId> [--json] [--from <sf-run.json>] [--detect-stage <id>] [--format envelope|handoff]
|
|
29
|
+
sf export-run --run <runId> [--from <sf-run.json>] [--out <file>]
|
|
30
|
+
sf ui [--port ${DEFAULT_PORT}] [--mcp-stateless]
|
|
31
|
+
sf mcp [--port ${DEFAULT_PORT}] [--mcp-stateless]
|
|
18
32
|
sf providers list
|
|
19
33
|
sf providers status [--provider <id>]
|
|
20
34
|
sf providers detect
|
|
21
35
|
sf providers source [get | set <pi_home|sf_owned>]
|
|
22
36
|
sf providers login <providerId> [--type api_key|oauth] [--api-key-env <VAR>]
|
|
23
37
|
sf providers logout <providerId>
|
|
38
|
+
sf skills list
|
|
39
|
+
sf skills install --from-path <dir> [--skill-name <name>]
|
|
40
|
+
sf skills install --from-zip <url-or-path> [--skill-name <name>] [--checksum sha256:<hex>]
|
|
24
41
|
sf --help
|
|
25
42
|
|
|
26
43
|
Stageflow (sf) runs YAML-defined automatic stage pipelines.
|
|
27
44
|
|
|
28
45
|
Store backend: SF_STORE=sqlite only. SF_STORE=disk is rejected; disk-era .stageflow/runs trees import when the SQLite store is empty. Data under .stageflow/.
|
|
29
46
|
|
|
47
|
+
${INIT_USAGE}
|
|
48
|
+
|
|
30
49
|
${RUN_USAGE}
|
|
31
50
|
|
|
32
51
|
${VALIDATE_USAGE}
|
|
33
52
|
|
|
34
|
-
${
|
|
53
|
+
${ARTIFACT_USAGE}
|
|
54
|
+
|
|
55
|
+
${ENVELOPE_USAGE}
|
|
56
|
+
|
|
57
|
+
${EXPORT_RUN_USAGE}
|
|
58
|
+
|
|
59
|
+
${PROVIDERS_USAGE}
|
|
60
|
+
|
|
61
|
+
${SKILLS_USAGE}`;
|
|
35
62
|
function parseArgs(argv) {
|
|
36
63
|
const args = argv.slice(2);
|
|
37
64
|
if (args.length === 0) {
|
|
@@ -44,7 +71,12 @@ function parseArgs(argv) {
|
|
|
44
71
|
const command = args[0];
|
|
45
72
|
if (command === "providers" ||
|
|
46
73
|
command === "validate" ||
|
|
47
|
-
command === "run"
|
|
74
|
+
command === "run" ||
|
|
75
|
+
command === "init" ||
|
|
76
|
+
command === "artifact" ||
|
|
77
|
+
command === "envelope" ||
|
|
78
|
+
command === "export-run" ||
|
|
79
|
+
command === "skills") {
|
|
48
80
|
return { help: false, command };
|
|
49
81
|
}
|
|
50
82
|
if (args.includes("--help") || args.includes("-h")) {
|
|
@@ -54,6 +86,7 @@ function parseArgs(argv) {
|
|
|
54
86
|
let pipeline;
|
|
55
87
|
let port;
|
|
56
88
|
let checkout;
|
|
89
|
+
let mcpStateless = false;
|
|
57
90
|
for (let i = 1; i < args.length; i++) {
|
|
58
91
|
if (args[i] === "--task") {
|
|
59
92
|
task = args[++i];
|
|
@@ -75,8 +108,11 @@ function parseArgs(argv) {
|
|
|
75
108
|
throw new Error(`Invalid --port: ${raw}`);
|
|
76
109
|
}
|
|
77
110
|
}
|
|
111
|
+
else if (args[i] === "--mcp-stateless") {
|
|
112
|
+
mcpStateless = true;
|
|
113
|
+
}
|
|
78
114
|
}
|
|
79
|
-
return { help: false, command, task, pipeline, port, checkout };
|
|
115
|
+
return { help: false, command, task, pipeline, port, checkout, mcpStateless };
|
|
80
116
|
}
|
|
81
117
|
export function parseRunStageArgs(argv) {
|
|
82
118
|
let runId;
|
|
@@ -85,6 +121,7 @@ export function parseRunStageArgs(argv) {
|
|
|
85
121
|
let resumeAnswer;
|
|
86
122
|
let attempt;
|
|
87
123
|
let sessionFilePath;
|
|
124
|
+
let operatorCwd;
|
|
88
125
|
let operatorAgentDir;
|
|
89
126
|
let skipGates = false;
|
|
90
127
|
for (let i = 0; i < argv.length; i++) {
|
|
@@ -130,6 +167,12 @@ export function parseRunStageArgs(argv) {
|
|
|
130
167
|
throw new Error("Missing value for --session-file");
|
|
131
168
|
}
|
|
132
169
|
}
|
|
170
|
+
else if (argv[i] === "--operator-cwd") {
|
|
171
|
+
operatorCwd = argv[++i];
|
|
172
|
+
if (operatorCwd === undefined) {
|
|
173
|
+
throw new Error("Missing value for --operator-cwd");
|
|
174
|
+
}
|
|
175
|
+
}
|
|
133
176
|
else if (argv[i] === "--operator-agent-dir") {
|
|
134
177
|
operatorAgentDir = argv[++i];
|
|
135
178
|
if (operatorAgentDir === undefined) {
|
|
@@ -143,6 +186,11 @@ export function parseRunStageArgs(argv) {
|
|
|
143
186
|
if (!runId || !stageId) {
|
|
144
187
|
throw new Error("Missing --run-id and/or --stage-id");
|
|
145
188
|
}
|
|
189
|
+
const operatorCatalog = resolveOperatorCatalog({
|
|
190
|
+
flags: { operatorCwd, operatorAgentDir },
|
|
191
|
+
env: process.env,
|
|
192
|
+
defaultCwd: process.cwd(),
|
|
193
|
+
});
|
|
146
194
|
return {
|
|
147
195
|
runId,
|
|
148
196
|
stageId,
|
|
@@ -151,9 +199,7 @@ export function parseRunStageArgs(argv) {
|
|
|
151
199
|
attempt,
|
|
152
200
|
sessionFilePath,
|
|
153
201
|
skipGates,
|
|
154
|
-
|
|
155
|
-
? { operatorCatalog: { cwd: process.cwd(), agentDir: operatorAgentDir } }
|
|
156
|
-
: {}),
|
|
202
|
+
operatorCatalog,
|
|
157
203
|
};
|
|
158
204
|
}
|
|
159
205
|
async function handleInternalRunStage(argv) {
|
|
@@ -194,22 +240,59 @@ async function main(argv) {
|
|
|
194
240
|
console.log(USAGE);
|
|
195
241
|
return argv.slice(2).length === 0 ? 1 : 0;
|
|
196
242
|
}
|
|
197
|
-
const
|
|
243
|
+
const ctx = await resolveStageflowContext(process.cwd());
|
|
244
|
+
if (parsed.command === "init") {
|
|
245
|
+
return runInitCommand(argv.slice(3), { cwd: ctx.invocationCwd });
|
|
246
|
+
}
|
|
198
247
|
if (parsed.command === "validate") {
|
|
199
|
-
return runValidateCommand(argv.slice(3), { cwd:
|
|
248
|
+
return runValidateCommand(argv.slice(3), { cwd: ctx.invocationCwd });
|
|
200
249
|
}
|
|
201
250
|
if (parsed.command === "run") {
|
|
202
|
-
return runRunCommand(argv.slice(3), {
|
|
251
|
+
return runRunCommand(argv.slice(3), {
|
|
252
|
+
cwd: ctx.invocationCwd,
|
|
253
|
+
projectRoot: ctx.projectRoot,
|
|
254
|
+
isGitProject: ctx.isGitProject,
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
if (parsed.command === "artifact") {
|
|
258
|
+
return runArtifactCommand(argv.slice(3), {
|
|
259
|
+
cwd: ctx.invocationCwd,
|
|
260
|
+
projectRoot: ctx.projectRoot,
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
if (parsed.command === "envelope") {
|
|
264
|
+
return runEnvelopeCommand(argv.slice(3), {
|
|
265
|
+
cwd: ctx.invocationCwd,
|
|
266
|
+
projectRoot: ctx.projectRoot,
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
if (parsed.command === "export-run") {
|
|
270
|
+
return runExportRunCommand(argv.slice(3), {
|
|
271
|
+
cwd: ctx.invocationCwd,
|
|
272
|
+
projectRoot: ctx.projectRoot,
|
|
273
|
+
});
|
|
203
274
|
}
|
|
204
275
|
if (parsed.command === "providers") {
|
|
205
|
-
return runProvidersCommand(argv.slice(3),
|
|
276
|
+
return runProvidersCommand(argv.slice(3), ctx.invocationCwd);
|
|
277
|
+
}
|
|
278
|
+
if (parsed.command === "skills") {
|
|
279
|
+
return runSkillsCommand(argv.slice(3), {
|
|
280
|
+
cwd: ctx.invocationCwd,
|
|
281
|
+
projectRoot: ctx.projectRoot,
|
|
282
|
+
});
|
|
206
283
|
}
|
|
207
|
-
const store = createRunStore({ rootDir });
|
|
284
|
+
const store = createRunStore({ rootDir: ctx.projectRoot });
|
|
208
285
|
if (parsed.command === "ui") {
|
|
286
|
+
const mcpStateless = resolveMcpStateless({
|
|
287
|
+
mcpStateless: parsed.mcpStateless,
|
|
288
|
+
});
|
|
209
289
|
const { url, mcpUrl } = await startUiServer({
|
|
210
290
|
agent: new PiAgentAdapter(),
|
|
211
291
|
store,
|
|
292
|
+
cwd: ctx.invocationCwd,
|
|
293
|
+
rootDir: ctx.projectRoot,
|
|
212
294
|
port: parsed.port,
|
|
295
|
+
mcpStateless,
|
|
213
296
|
});
|
|
214
297
|
console.log(`Operator console: ${url}`);
|
|
215
298
|
console.log(`MCP endpoint: ${mcpUrl}`);
|
|
@@ -217,6 +300,22 @@ async function main(argv) {
|
|
|
217
300
|
await new Promise(() => undefined);
|
|
218
301
|
return 0;
|
|
219
302
|
}
|
|
303
|
+
if (parsed.command === "mcp") {
|
|
304
|
+
const mcpStateless = resolveMcpStateless({
|
|
305
|
+
mcpStateless: parsed.mcpStateless,
|
|
306
|
+
});
|
|
307
|
+
const { mcpUrl } = await startMcpServer({
|
|
308
|
+
agent: new PiAgentAdapter(),
|
|
309
|
+
store,
|
|
310
|
+
cwd: ctx.invocationCwd,
|
|
311
|
+
rootDir: ctx.projectRoot,
|
|
312
|
+
port: parsed.port,
|
|
313
|
+
mcpStateless,
|
|
314
|
+
});
|
|
315
|
+
console.log(`MCP endpoint: ${mcpUrl}`);
|
|
316
|
+
await new Promise(() => undefined);
|
|
317
|
+
return 0;
|
|
318
|
+
}
|
|
220
319
|
if (parsed.command === "internal") {
|
|
221
320
|
const subArgs = argv.slice(3);
|
|
222
321
|
const subcommand = subArgs[0];
|
|
@@ -235,16 +334,23 @@ async function main(argv) {
|
|
|
235
334
|
return 1;
|
|
236
335
|
}
|
|
237
336
|
}
|
|
337
|
+
function normalizeCliEntry(filePath) {
|
|
338
|
+
const resolved = path.resolve(filePath);
|
|
339
|
+
let canonical;
|
|
340
|
+
try {
|
|
341
|
+
canonical = realpathSync(resolved);
|
|
342
|
+
}
|
|
343
|
+
catch {
|
|
344
|
+
canonical = resolved;
|
|
345
|
+
}
|
|
346
|
+
return canonical.replace(/\.(?:[cm]?[jt]s)$/i, "");
|
|
347
|
+
}
|
|
348
|
+
export function sameCliEntry(a, b) {
|
|
349
|
+
return normalizeCliEntry(a) === normalizeCliEntry(b);
|
|
350
|
+
}
|
|
238
351
|
function isDirectCliInvocation() {
|
|
239
352
|
const self = fileURLToPath(import.meta.url);
|
|
240
|
-
return process.argv.slice(1).some((arg) =>
|
|
241
|
-
try {
|
|
242
|
-
return realpathSync(path.resolve(arg)) === realpathSync(self);
|
|
243
|
-
}
|
|
244
|
-
catch {
|
|
245
|
-
return false;
|
|
246
|
-
}
|
|
247
|
-
});
|
|
353
|
+
return process.argv.slice(1).some((arg) => sameCliEntry(arg, self));
|
|
248
354
|
}
|
|
249
355
|
if (isDirectCliInvocation()) {
|
|
250
356
|
main(process.argv)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { StageGateKind } from "../types/stage.js";
|
|
2
|
+
import type { LoadedManifest } from "../types/stageflowManifest.js";
|
|
3
|
+
import type { LoadIssue } from "./loadOutcome.js";
|
|
4
|
+
import type { CatalogContext } from "./resolveCatalogContext.js";
|
|
5
|
+
import { type CatalogManifestStatus, type StageflowContext } from "../project/resolveStageflowContext.js";
|
|
6
|
+
export type TaskListing = {
|
|
7
|
+
path: string;
|
|
8
|
+
id: string;
|
|
9
|
+
goal: string;
|
|
10
|
+
};
|
|
11
|
+
export type PipelineStageListing = {
|
|
12
|
+
id: string;
|
|
13
|
+
gate_kinds?: StageGateKind[];
|
|
14
|
+
uses_path?: string;
|
|
15
|
+
inline?: boolean;
|
|
16
|
+
};
|
|
17
|
+
export type PipelineListing = {
|
|
18
|
+
path: string;
|
|
19
|
+
id: string;
|
|
20
|
+
stages: PipelineStageListing[];
|
|
21
|
+
};
|
|
22
|
+
export type CatalogBrowseWarning = {
|
|
23
|
+
path: string;
|
|
24
|
+
kind: "pipeline" | "task";
|
|
25
|
+
error: string;
|
|
26
|
+
};
|
|
27
|
+
export type CatalogBrowseResult = {
|
|
28
|
+
projectRoot: string | null;
|
|
29
|
+
manifest: LoadedManifest | null;
|
|
30
|
+
manifestStatus: CatalogManifestStatus;
|
|
31
|
+
issues: LoadIssue[];
|
|
32
|
+
pipelines: PipelineListing[];
|
|
33
|
+
tasks: TaskListing[];
|
|
34
|
+
models: string[];
|
|
35
|
+
warnings: CatalogBrowseWarning[];
|
|
36
|
+
};
|
|
37
|
+
export type CatalogScanPaths = {
|
|
38
|
+
pipelinePaths: string[];
|
|
39
|
+
taskPaths: string[];
|
|
40
|
+
};
|
|
41
|
+
export declare function getCatalogScanPaths(ctx: CatalogContext): Promise<CatalogScanPaths | null>;
|
|
42
|
+
export declare function browseCatalog(invocationCwd: string | StageflowContext): Promise<CatalogBrowseResult>;
|
|
43
|
+
export declare function listPipelinesForContext(ctx: CatalogContext): Promise<PipelineListing[]>;
|
|
44
|
+
export declare function listTasksForContext(ctx: CatalogContext): Promise<TaskListing[]>;
|
|
45
|
+
export declare function listModelsForContext(ctx: CatalogContext): Promise<string[]>;
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { loadPipeline } from "./loadPipeline.js";
|
|
3
|
+
import { loadTask } from "./loadTask.js";
|
|
4
|
+
import { resolveStageflowContext, } from "../project/resolveStageflowContext.js";
|
|
5
|
+
import { scanCatalogPaths } from "./scanCatalogPaths.js";
|
|
6
|
+
const BAKED_MODEL_IDS = [
|
|
7
|
+
"anthropic/claude-sonnet-4-5",
|
|
8
|
+
"cursor/auto",
|
|
9
|
+
"cursor/composer-2-5",
|
|
10
|
+
];
|
|
11
|
+
function repoRelPath(projectRoot, absPath) {
|
|
12
|
+
return path.relative(projectRoot, absPath).replace(/\\/g, "/");
|
|
13
|
+
}
|
|
14
|
+
function mapStageListing(stage, source, projectRoot) {
|
|
15
|
+
const listing = {
|
|
16
|
+
id: stage.id,
|
|
17
|
+
...(stage.gate_kinds ? { gate_kinds: stage.gate_kinds } : {}),
|
|
18
|
+
};
|
|
19
|
+
if (source?.kind === "inline") {
|
|
20
|
+
listing.inline = true;
|
|
21
|
+
}
|
|
22
|
+
else if (source?.kind === "file") {
|
|
23
|
+
listing.uses_path = repoRelPath(projectRoot, source.path);
|
|
24
|
+
}
|
|
25
|
+
return listing;
|
|
26
|
+
}
|
|
27
|
+
function bakedModels() {
|
|
28
|
+
return [...BAKED_MODEL_IDS].sort((a, b) => a.localeCompare(b));
|
|
29
|
+
}
|
|
30
|
+
function catalogReadyFromStageflow(ctx) {
|
|
31
|
+
return ctx.isGitProject && ctx.manifestStatus === "ok" && ctx.manifest !== null;
|
|
32
|
+
}
|
|
33
|
+
function catalogReady(ctx) {
|
|
34
|
+
return ctx.manifestStatus === "ok" && ctx.projectRoot !== null && ctx.manifest !== null;
|
|
35
|
+
}
|
|
36
|
+
export async function getCatalogScanPaths(ctx) {
|
|
37
|
+
if (!catalogReady(ctx)) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
const [pipelinePaths, taskPaths] = await Promise.all([
|
|
41
|
+
scanCatalogPaths(ctx.manifest, "pipeline"),
|
|
42
|
+
scanCatalogPaths(ctx.manifest, "task"),
|
|
43
|
+
]);
|
|
44
|
+
return { pipelinePaths, taskPaths };
|
|
45
|
+
}
|
|
46
|
+
async function listTasksFromManifest(projectRoot, manifest, warnings) {
|
|
47
|
+
const filePaths = await scanCatalogPaths(manifest, "task");
|
|
48
|
+
const listings = [];
|
|
49
|
+
for (const filePath of filePaths) {
|
|
50
|
+
try {
|
|
51
|
+
const task = await loadTask(filePath);
|
|
52
|
+
listings.push({
|
|
53
|
+
path: repoRelPath(projectRoot, filePath),
|
|
54
|
+
id: task.id,
|
|
55
|
+
goal: task.goal,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
warnings.push({
|
|
60
|
+
path: repoRelPath(projectRoot, filePath),
|
|
61
|
+
kind: "task",
|
|
62
|
+
error: err instanceof Error ? err.message : String(err),
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
listings.sort((a, b) => {
|
|
67
|
+
const pathCmp = a.path.localeCompare(b.path);
|
|
68
|
+
if (pathCmp !== 0)
|
|
69
|
+
return pathCmp;
|
|
70
|
+
return a.id.localeCompare(b.id);
|
|
71
|
+
});
|
|
72
|
+
return listings;
|
|
73
|
+
}
|
|
74
|
+
async function listPipelinesFromManifest(projectRoot, manifest, warnings) {
|
|
75
|
+
const filePaths = await scanCatalogPaths(manifest, "pipeline");
|
|
76
|
+
const listings = [];
|
|
77
|
+
for (const filePath of filePaths) {
|
|
78
|
+
try {
|
|
79
|
+
const loaded = await loadPipeline(filePath, { cwd: projectRoot });
|
|
80
|
+
listings.push({
|
|
81
|
+
path: repoRelPath(projectRoot, filePath),
|
|
82
|
+
id: loaded.pipeline.id,
|
|
83
|
+
stages: loaded.stages.map((stage) => mapStageListing(stage, loaded.stageSources?.[stage.id], projectRoot)),
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
warnings.push({
|
|
88
|
+
path: repoRelPath(projectRoot, filePath),
|
|
89
|
+
kind: "pipeline",
|
|
90
|
+
error: err instanceof Error ? err.message : String(err),
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
listings.sort((a, b) => {
|
|
95
|
+
const pathCmp = a.path.localeCompare(b.path);
|
|
96
|
+
if (pathCmp !== 0)
|
|
97
|
+
return pathCmp;
|
|
98
|
+
return a.id.localeCompare(b.id);
|
|
99
|
+
});
|
|
100
|
+
return listings;
|
|
101
|
+
}
|
|
102
|
+
async function listModelsFromManifest(projectRoot, manifest) {
|
|
103
|
+
const models = new Set(BAKED_MODEL_IDS);
|
|
104
|
+
const filePaths = await scanCatalogPaths(manifest, "pipeline");
|
|
105
|
+
for (const filePath of filePaths) {
|
|
106
|
+
try {
|
|
107
|
+
const loaded = await loadPipeline(filePath, { cwd: projectRoot });
|
|
108
|
+
for (const stage of loaded.stages) {
|
|
109
|
+
if (stage.model.trim()) {
|
|
110
|
+
models.add(stage.model);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
// skip invalid pipelines
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return [...models].sort((a, b) => a.localeCompare(b));
|
|
119
|
+
}
|
|
120
|
+
export async function browseCatalog(invocationCwd) {
|
|
121
|
+
const ctx = typeof invocationCwd === "string"
|
|
122
|
+
? await resolveStageflowContext(invocationCwd)
|
|
123
|
+
: invocationCwd;
|
|
124
|
+
const base = {
|
|
125
|
+
projectRoot: ctx.isGitProject ? ctx.projectRoot : null,
|
|
126
|
+
manifest: ctx.manifest,
|
|
127
|
+
manifestStatus: ctx.manifestStatus,
|
|
128
|
+
issues: ctx.manifestIssues,
|
|
129
|
+
};
|
|
130
|
+
if (!catalogReadyFromStageflow(ctx)) {
|
|
131
|
+
return {
|
|
132
|
+
...base,
|
|
133
|
+
pipelines: [],
|
|
134
|
+
tasks: [],
|
|
135
|
+
models: bakedModels(),
|
|
136
|
+
warnings: [],
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
const warnings = [];
|
|
140
|
+
const [pipelines, tasks, models] = await Promise.all([
|
|
141
|
+
listPipelinesFromManifest(ctx.projectRoot, ctx.manifest, warnings),
|
|
142
|
+
listTasksFromManifest(ctx.projectRoot, ctx.manifest, warnings),
|
|
143
|
+
listModelsFromManifest(ctx.projectRoot, ctx.manifest),
|
|
144
|
+
]);
|
|
145
|
+
return {
|
|
146
|
+
...base,
|
|
147
|
+
pipelines,
|
|
148
|
+
tasks,
|
|
149
|
+
models,
|
|
150
|
+
warnings,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
export async function listPipelinesForContext(ctx) {
|
|
154
|
+
if (!catalogReady(ctx)) {
|
|
155
|
+
return [];
|
|
156
|
+
}
|
|
157
|
+
return listPipelinesFromManifest(ctx.projectRoot, ctx.manifest, []);
|
|
158
|
+
}
|
|
159
|
+
export async function listTasksForContext(ctx) {
|
|
160
|
+
if (!catalogReady(ctx)) {
|
|
161
|
+
return [];
|
|
162
|
+
}
|
|
163
|
+
return listTasksFromManifest(ctx.projectRoot, ctx.manifest, []);
|
|
164
|
+
}
|
|
165
|
+
export async function listModelsForContext(ctx) {
|
|
166
|
+
if (!catalogReady(ctx)) {
|
|
167
|
+
return bakedModels();
|
|
168
|
+
}
|
|
169
|
+
return listModelsFromManifest(ctx.projectRoot, ctx.manifest);
|
|
170
|
+
}
|
|
@@ -1,11 +1,20 @@
|
|
|
1
|
+
import type { StageGateKind } from "../types/stage.js";
|
|
1
2
|
import type { PipelineListing } from "./listConfig.js";
|
|
3
|
+
export type CreatePipelineStageInline = {
|
|
4
|
+
system_prompt: string;
|
|
5
|
+
model: string;
|
|
6
|
+
gate_kinds?: StageGateKind[];
|
|
7
|
+
};
|
|
2
8
|
export type CreatePipelineStageRef = {
|
|
3
9
|
id: string;
|
|
4
10
|
needs?: string;
|
|
11
|
+
uses?: string;
|
|
12
|
+
inline?: CreatePipelineStageInline;
|
|
5
13
|
};
|
|
6
14
|
export type CreatePipelineInput = {
|
|
15
|
+
directory: string;
|
|
7
16
|
id: string;
|
|
8
|
-
stages: CreatePipelineStageRef[]
|
|
17
|
+
stages: CreatePipelineStageRef[];
|
|
9
18
|
};
|
|
10
19
|
export type CreatePipelineParseError = {
|
|
11
20
|
ok: false;
|
|
@@ -20,7 +29,7 @@ export type CreatePipelineResult = {
|
|
|
20
29
|
status: 400 | 409 | 422 | 500;
|
|
21
30
|
error: string;
|
|
22
31
|
};
|
|
23
|
-
export declare function normalizeCreatePipelineStages(stages: CreatePipelineStageRef[]
|
|
32
|
+
export declare function normalizeCreatePipelineStages(stages: CreatePipelineStageRef[]): CreatePipelineStageRef[];
|
|
24
33
|
export declare function parseCreatePipelineBody(body: unknown): CreatePipelineInput | CreatePipelineParseError;
|
|
25
34
|
export declare function pipelineConfigToYaml(pipeline: {
|
|
26
35
|
id: string;
|
|
@@ -28,4 +37,4 @@ export declare function pipelineConfigToYaml(pipeline: {
|
|
|
28
37
|
}, options: {
|
|
29
38
|
format: "linear" | "dag";
|
|
30
39
|
}): string;
|
|
31
|
-
export declare function createPipeline(
|
|
40
|
+
export declare function createPipeline(projectRoot: string, input: CreatePipelineInput): Promise<CreatePipelineResult>;
|