stageflow 0.32.0 → 0.35.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 +4 -3
- package/dist/agent/adapterSpill.d.ts +14 -0
- package/dist/agent/adapterSpill.js +83 -0
- package/dist/agent/agentBackend.d.ts +2 -2
- package/dist/agent/agentBackend.js +2 -2
- package/dist/agent/claudeAdapter.d.ts +13 -2
- package/dist/agent/claudeAdapter.js +50 -6
- package/dist/agent/cursorProvider.d.ts +3 -0
- package/dist/agent/cursorProvider.js +23 -6
- package/dist/agent/fakeAgent.d.ts +3 -3
- package/dist/agent/fakeAgent.js +0 -6
- package/dist/agent/piAdapter.d.ts +2 -2
- package/dist/agent/piAdapter.js +116 -15
- package/dist/agent/piIsolatedMcp.d.ts +1 -0
- package/dist/agent/piIsolatedMcp.js +19 -1
- package/dist/agent/piIsolatedMcpProbe.d.ts +11 -0
- package/dist/agent/piIsolatedMcpProbe.js +20 -0
- package/dist/agent/port.d.ts +2 -2
- package/dist/agent/providerAuth.d.ts +6 -0
- package/dist/agent/providerAuth.js +86 -17
- package/dist/agent/{resolveAgentPort.d.ts → resolveStagePort.d.ts} +8 -6
- package/dist/agent/{resolveAgentPort.js → resolveStagePort.js} +13 -9
- package/dist/agent/stageTurnDriver.d.ts +33 -0
- package/dist/agent/stageTurnDriver.js +64 -0
- package/dist/agent/toolOutputBudget.d.ts +46 -0
- package/dist/agent/toolOutputBudget.js +97 -0
- package/dist/agent/toolOutputBudgetExtension.d.ts +22 -0
- package/dist/agent/toolOutputBudgetExtension.js +141 -0
- package/dist/agent/toolOutputSpill.d.ts +34 -0
- package/dist/agent/toolOutputSpill.js +85 -0
- package/dist/browser/agentBrowserLiveViewRelay.d.ts +41 -0
- package/dist/browser/agentBrowserLiveViewRelay.js +801 -0
- package/dist/browser/anchor.d.ts +2 -0
- package/dist/browser/anchor.js +2 -1
- package/dist/browser/auditSink.d.ts +8 -0
- package/dist/browser/browserHost.d.ts +29 -0
- package/dist/browser/browserSweep.d.ts +4 -1
- package/dist/browser/browserSweep.js +7 -0
- package/dist/browser/browserTeardown.d.ts +1 -0
- package/dist/browser/browserTeardown.js +32 -2
- package/dist/browser/containerBrowserEndpoint.d.ts +11 -0
- package/dist/browser/containerBrowserEndpoint.js +57 -0
- package/dist/browser/containerBrowserHost.d.ts +24 -0
- package/dist/browser/containerBrowserHost.js +147 -0
- package/dist/browser/dockerSandboxOrchestrator.d.ts +26 -0
- package/dist/browser/dockerSandboxOrchestrator.js +142 -0
- package/dist/browser/fakeLiveViewRelay.d.ts +15 -0
- package/dist/browser/fakeLiveViewRelay.js +94 -0
- package/dist/browser/fakeLiveViewSource.d.ts +6 -0
- package/dist/browser/fakeLiveViewSource.js +16 -0
- package/dist/browser/fakeRemoteBrowserHost.d.ts +2 -1
- package/dist/browser/fakeRemoteBrowserHost.js +2 -1
- package/dist/browser/fakeSandboxOrchestrator.d.ts +9 -0
- package/dist/browser/fakeSandboxOrchestrator.js +44 -0
- package/dist/browser/gateHandoff.d.ts +0 -2
- package/dist/browser/gateHandoff.js +5 -11
- package/dist/browser/hostCapabilities.d.ts +23 -0
- package/dist/browser/hostCapabilities.js +23 -0
- package/dist/browser/humanLogin.d.ts +2 -2
- package/dist/browser/humanLogin.js +11 -2
- package/dist/browser/liveViewPersisted.d.ts +11 -0
- package/dist/browser/liveViewPersisted.js +22 -0
- package/dist/browser/liveViewRelay.d.ts +76 -0
- package/dist/browser/liveViewRelay.js +1 -0
- package/dist/browser/liveViewSessions.d.ts +25 -0
- package/dist/browser/liveViewSessions.js +139 -0
- package/dist/browser/liveViewSource.d.ts +25 -0
- package/dist/browser/liveViewSource.js +7 -0
- package/dist/browser/liveViewTickets.d.ts +46 -0
- package/dist/browser/liveViewTickets.js +122 -0
- package/dist/browser/localBrowserHost.d.ts +10 -0
- package/dist/browser/localBrowserHost.js +53 -7
- package/dist/browser/ownerScope.d.ts +10 -0
- package/dist/browser/ownerScope.js +6 -0
- package/dist/browser/profileStore.d.ts +5 -2
- package/dist/browser/profileStore.js +3 -5
- package/dist/browser/sandboxOrchestrator.d.ts +60 -0
- package/dist/browser/sandboxOrchestrator.js +8 -0
- package/dist/browser/sessionApiSandboxOrchestrator.d.ts +34 -0
- package/dist/browser/sessionApiSandboxOrchestrator.js +108 -0
- package/dist/browser/stageBrowserEnv.d.ts +7 -0
- package/dist/browser/stageBrowserEnv.js +53 -15
- package/dist/browser/stageHandoff.d.ts +47 -0
- package/dist/browser/stageHandoff.js +101 -0
- package/dist/browser/stageProfileLock.d.ts +1 -0
- package/dist/browser/stageProfileLock.js +1 -3
- package/dist/browser/volumeProfileStore.d.ts +7 -0
- package/dist/browser/volumeProfileStore.js +35 -0
- package/dist/cli/browserCommand.d.ts +3 -1
- package/dist/cli/browserCommand.js +25 -20
- package/dist/cli/resolveCliProjectRoot.d.ts +7 -0
- package/dist/cli/resolveCliProjectRoot.js +27 -0
- package/dist/cli/runCommand.d.ts +1 -1
- package/dist/cli/runCommand.js +59 -17
- package/dist/cli/skillsCommand.d.ts +20 -0
- package/dist/cli/skillsCommand.js +74 -31
- package/dist/cli/validateCommand.d.ts +1 -1
- package/dist/cli/validateCommand.js +22 -4
- package/dist/cli.js +4 -4
- package/dist/config/browseCatalog.d.ts +2 -0
- package/dist/config/browseCatalog.js +6 -0
- package/dist/config/catalogRelativePath.d.ts +4 -0
- package/dist/config/catalogRelativePath.js +37 -9
- package/dist/config/createStage.d.ts +1 -0
- package/dist/config/createStage.js +11 -2
- package/dist/config/createTask.d.ts +30 -0
- package/dist/config/createTask.js +161 -0
- package/dist/config/createTrigger.d.ts +15 -0
- package/dist/config/createTrigger.js +32 -25
- package/dist/config/draftPackage.d.ts +41 -0
- package/dist/config/draftPackage.js +216 -23
- package/dist/config/ensureCatalogScanRoot.d.ts +2 -1
- package/dist/config/ensureCatalogScanRoot.js +6 -2
- package/dist/config/findTaskInCatalog.d.ts +33 -0
- package/dist/config/findTaskInCatalog.js +69 -0
- package/dist/config/hostConfig.d.ts +21 -0
- package/dist/config/hostConfig.js +113 -1
- package/dist/config/importTask.d.ts +19 -0
- package/dist/config/importTask.js +133 -0
- package/dist/config/installSkillRequest.d.ts +40 -0
- package/dist/config/installSkillRequest.js +286 -0
- package/dist/config/listConfig.d.ts +0 -16
- package/dist/config/listConfig.js +0 -3
- package/dist/config/loadOutcome.d.ts +11 -6
- package/dist/config/loadPipeline.js +0 -1
- package/dist/config/loadStage.js +2 -0
- package/dist/config/loadStageflowManifest.js +4 -1
- package/dist/config/loadTask.js +2 -0
- package/dist/config/loadTrigger.js +2 -0
- package/dist/config/mergePipelineIncludes.js +3 -0
- package/dist/config/normalizePipelineStageEntry.js +10 -1
- package/dist/config/printTargetYaml.js +0 -1
- package/dist/config/publishDraftPackage.d.ts +5 -1
- package/dist/config/publishDraftPackage.js +4 -1
- package/dist/config/resolveCatalogRoots.d.ts +4 -1
- package/dist/config/resolveCatalogRoots.js +18 -1
- package/dist/config/skillUsageIndex.d.ts +6 -0
- package/dist/config/skillUsageIndex.js +39 -0
- package/dist/config/stageBrowser.js +13 -0
- package/dist/config/triggerAdapterStatus.d.ts +11 -0
- package/dist/config/triggerAdapterStatus.js +90 -0
- package/dist/config/triggerCatalog.d.ts +41 -2
- package/dist/config/triggerCatalog.js +107 -15
- package/dist/config/updateTask.d.ts +30 -0
- package/dist/config/updateTask.js +119 -0
- package/dist/config/updateTrigger.d.ts +38 -0
- package/dist/config/updateTrigger.js +220 -0
- package/dist/config/validateCatalog.d.ts +6 -2
- package/dist/config/validateCatalog.js +48 -7
- package/dist/config/workshopCatalogFilenames.d.ts +37 -0
- package/dist/config/workshopCatalogFilenames.js +125 -0
- package/dist/config/workshopCatalogRepair.d.ts +7 -0
- package/dist/config/workshopCatalogRepair.js +144 -0
- package/dist/config/yamlParsePosition.d.ts +4 -0
- package/dist/config/yamlParsePosition.js +9 -0
- package/dist/hosted/containment.d.ts +3 -0
- package/dist/hosted/containment.js +36 -0
- package/dist/hosted/errors.d.ts +21 -0
- package/dist/hosted/errors.js +30 -0
- package/dist/hosted/packageSkills.d.ts +3 -0
- package/dist/hosted/packageSkills.js +80 -0
- package/dist/hosted/runtime.d.ts +12 -0
- package/dist/hosted/runtime.js +596 -0
- package/dist/hosted/sequencer.d.ts +28 -0
- package/dist/hosted/sequencer.js +129 -0
- package/dist/hosted/translate.d.ts +3 -0
- package/dist/hosted/translate.js +43 -0
- package/dist/hosted/types.d.ts +108 -0
- package/dist/hosted/types.js +10 -0
- package/dist/index.d.ts +9 -1
- package/dist/index.js +6 -0
- package/dist/mcp/getStartedTool.js +15 -6
- package/dist/mcp/triggerTools.js +2 -8
- package/dist/operatorAgent/agentPort.d.ts +11 -0
- package/dist/operatorAgent/agentPort.js +12 -0
- package/dist/operatorAgent/index.d.ts +1 -0
- package/dist/operatorAgent/index.js +1 -0
- package/dist/operatorAgent/piModel.js +26 -6
- package/dist/operatorAgent/profiles/workshopAuthorPlaybook.d.ts +1 -1
- package/dist/operatorAgent/profiles/workshopAuthorPlaybook.js +4 -2
- package/dist/operatorAgent/profiles/workshopAuthorTools.js +103 -16
- package/dist/package-meta.d.ts +1 -1
- package/dist/package-meta.js +1 -1
- package/dist/project/ensureProjectRootsFromEnv.d.ts +3 -0
- package/dist/project/ensureProjectRootsFromEnv.js +22 -0
- package/dist/project/globalHome.d.ts +1 -0
- package/dist/project/globalHome.js +18 -0
- package/dist/project/workspaceCatalog.d.ts +10 -0
- package/dist/project/workspaceCatalog.js +91 -0
- package/dist/projection/projectRun.d.ts +0 -1
- package/dist/projection/projectRun.js +0 -1
- package/dist/runstore/backup.js +14 -4
- package/dist/runstore/port.d.ts +11 -1
- package/dist/runstore/restore.js +5 -2
- package/dist/runstore/sqlite/SqliteRunStore.d.ts +8 -0
- package/dist/runstore/sqlite/SqliteRunStore.js +29 -9
- package/dist/runstore/sqlite/migrations/012-trigger-fires.d.ts +7 -0
- package/dist/runstore/sqlite/migrations/012-trigger-fires.js +18 -0
- package/dist/runstore/sqlite/migrations/index.js +2 -0
- package/dist/runstore/stageSnapshot.d.ts +3 -1
- package/dist/runstore/stageSnapshot.js +19 -0
- package/dist/runstore/workspaceLayout.js +27 -0
- package/dist/runstore/writeContainedArtifact.d.ts +1 -0
- package/dist/runstore/writeContainedArtifact.js +52 -0
- package/dist/runtime/containerLimits.d.ts +0 -3
- package/dist/runtime/containerLimits.js +0 -5
- package/dist/runtime/credentialBinding.d.ts +3 -0
- package/dist/runtime/credentialBinding.js +23 -6
- package/dist/runtime/emailSource.js +20 -28
- package/dist/runtime/githubPollSource.js +20 -28
- package/dist/runtime/pipelineRunner.d.ts +4 -4
- package/dist/runtime/pipelineScheduler.d.ts +2 -2
- package/dist/runtime/pipelineScheduler.js +3 -0
- package/dist/runtime/resumeReconstruct.d.ts +2 -2
- package/dist/runtime/resumeTimedOut.d.ts +2 -2
- package/dist/runtime/runManager.d.ts +18 -2
- package/dist/runtime/runManager.js +95 -30
- package/dist/runtime/runRetentionSweep.d.ts +0 -2
- package/dist/runtime/runRetentionSweep.js +0 -8
- package/dist/runtime/runRetryCoordinator.d.ts +2 -2
- package/dist/runtime/scheduleSource.js +15 -24
- package/dist/runtime/stageAttemptBootstrap.d.ts +2 -2
- package/dist/runtime/stageAttemptBootstrap.js +10 -1
- package/dist/runtime/stageProcessLauncher.js +2 -2
- package/dist/runtime/stageRoots.js +12 -1
- package/dist/runtime/stageRunner.d.ts +2 -2
- package/dist/runtime/stageRunner.js +8 -2
- package/dist/runtime/stageWorker.js +2 -2
- package/dist/runtime/triggerPort.d.ts +5 -3
- package/dist/runtime/triggerRunner.d.ts +1 -0
- package/dist/runtime/triggerRunner.js +27 -20
- package/dist/runtime/webhookAccept.d.ts +25 -0
- package/dist/runtime/webhookAccept.js +56 -0
- package/dist/server/bootstrap.d.ts +7 -2
- package/dist/server/bootstrap.js +15 -1
- package/dist/server/controlToken.d.ts +1 -1
- package/dist/server/controlToken.js +18 -2
- package/dist/server/healthSurfaces.d.ts +12 -0
- package/dist/server/healthSurfaces.js +27 -6
- package/dist/server/http.d.ts +19 -10
- package/dist/server/http.js +605 -85
- package/dist/server/liveViewPath.d.ts +9 -0
- package/dist/server/liveViewPath.js +8 -0
- package/dist/server/liveViewRoutes.d.ts +58 -0
- package/dist/server/liveViewRoutes.js +565 -0
- package/dist/server/mcpHost.d.ts +4 -2
- package/dist/server/mcpHost.js +2 -0
- package/dist/server/readCatalogFile.d.ts +29 -0
- package/dist/server/readCatalogFile.js +215 -0
- package/dist/server/triggerRoutes.d.ts +1 -0
- package/dist/server/triggerRoutes.js +200 -73
- package/dist/tools/readEmail.d.ts +3 -3
- package/dist/tools/writeStageArtifact.d.ts +9 -0
- package/dist/tools/writeStageArtifact.js +2 -47
- package/dist/types/pipeline.d.ts +1 -1
- package/dist/types/stage.d.ts +1 -1
- package/dist/types/stageflowManifest.d.ts +1 -1
- package/dist/ui/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
- package/dist/ui/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
- package/dist/ui/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
- package/dist/ui/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
- package/dist/ui/assets/geist-mono-cyrillic-ext-wght-normal-X_5orZeX.woff2 +0 -0
- package/dist/ui/assets/geist-mono-cyrillic-wght-normal-DiZS0aHC.woff2 +0 -0
- package/dist/ui/assets/geist-mono-latin-ext-wght-normal-Bwz-egvJ.woff2 +0 -0
- package/dist/ui/assets/geist-mono-latin-wght-normal-XN7g48iV.woff2 +0 -0
- package/dist/ui/assets/geist-mono-symbols2-wght-normal-CO5SzqOn.woff2 +0 -0
- package/dist/ui/assets/geist-mono-vietnamese-wght-normal-DadHysG0.woff2 +0 -0
- package/dist/ui/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
- package/dist/ui/assets/index-BoFPkKFg.js +256 -0
- package/dist/ui/assets/{index-Bv4p1aPK.css → index-CIPbbBUi.css} +1 -1
- package/dist/ui/index.html +4 -4
- package/dist/workshop/autosave.d.ts +2 -2
- package/dist/workshop/autosave.js +4 -6
- package/dist/workshop/buildStore.d.ts +2 -0
- package/dist/workshop/chatAttachments.d.ts +27 -0
- package/dist/workshop/chatAttachments.js +98 -0
- package/dist/workshop/chatTurn.d.ts +5 -2
- package/dist/workshop/chatTurn.js +22 -18
- package/dist/workshop/sessionMutations.d.ts +17 -0
- package/dist/workshop/sessionMutations.js +107 -0
- package/dist/workshop/sessionStore.d.ts +10 -0
- package/dist/workshop/sessionStore.js +52 -0
- package/dist/workshop/workshopPin.d.ts +4 -3
- package/dist/workshop/workshopPin.js +26 -6
- package/dist/workshop/workshopTranscriptTurn.d.ts +8 -0
- package/dist/workshop/workshopTranscriptTurn.js +46 -0
- package/examples/README.md +1 -1
- package/examples/archify-on-pr/README.md +1 -1
- package/examples/archify-on-pr/archify-on-pr.pipeline.yaml +0 -1
- package/examples/archify-on-pr/author-diagrams.yaml +1 -0
- package/examples/conditional-fork/branch-a.yaml +1 -1
- package/examples/conditional-fork/decide.yaml +2 -1
- package/examples/feature-loop/{implement.yaml → feature-implement.yaml} +1 -1
- package/examples/feature-loop/feature-loop.pipeline.yaml +10 -10
- package/examples/feature-loop/{plan.yaml → feature-plan.yaml} +1 -1
- package/examples/feature-loop/{review.yaml → feature-review.yaml} +1 -1
- package/examples/feedback-loop/{implement.yaml → feedback-implement.yaml} +1 -1
- package/examples/feedback-loop/feedback-loop-wait-human.pipeline.yaml +9 -9
- package/examples/feedback-loop/feedback-loop.pipeline.yaml +9 -9
- package/examples/feedback-loop/{plan.yaml → feedback-plan.yaml} +1 -1
- package/examples/feedback-loop/{review.yaml → feedback-review.yaml} +1 -1
- package/examples/generic-fan-in/{research.yaml → fan-in-research.yaml} +1 -1
- package/examples/generic-fan-in/generic-fan-in-accepted.pipeline.yaml +3 -3
- package/examples/generic-fan-in/generic-fan-in.pipeline.yaml +3 -3
- package/examples/hello-world/{research.yaml → hello-research.yaml} +1 -1
- package/examples/hello-world/hello.pipeline.yaml +2 -2
- package/examples/mcp-hitl-tour/{review.yaml → mcp-hitl-review.yaml} +1 -1
- package/examples/mcp-hitl-tour/mcp-hitl-tour.pipeline.yaml +3 -3
- package/examples/oss-issue-contribution/oss-explain-fix.yaml +1 -0
- package/examples/oss-issue-contribution/oss-explain-issue.yaml +1 -0
- package/examples/oss-issue-contribution/oss-issue-contribution.pipeline.yaml +0 -2
- package/examples/stageflow.yaml +6 -0
- package/examples/triggers/sample-github-pr.trigger.yaml +12 -0
- package/examples/triggers/sample-inbox-email.trigger.yaml +14 -0
- package/examples/triggers/sample-manual-hello.trigger.yaml +5 -0
- package/examples/triggers/sample-nightly-hello.trigger.yaml +8 -0
- package/examples/triggers/sample-signed-webhook.trigger.yaml +11 -0
- package/examples/triggers-readiness/README.md +48 -0
- package/examples/triggers-readiness/readiness-emit.yaml +18 -0
- package/examples/triggers-readiness/readiness.pipeline.yaml +4 -0
- package/examples/triggers-readiness/readiness.task.yaml +6 -0
- package/examples/triggers-readiness/stageflow.yaml +13 -0
- package/examples/triggers-readiness/triggers/readiness-dynamic-manual.trigger.yaml +4 -0
- package/examples/triggers-readiness/triggers/readiness-email.trigger.yaml +12 -0
- package/examples/triggers-readiness/triggers/readiness-github-pr.trigger.yaml +12 -0
- package/examples/triggers-readiness/triggers/readiness-manual.trigger.yaml +5 -0
- package/examples/triggers-readiness/triggers/readiness-schedule.trigger.yaml +8 -0
- package/examples/triggers-readiness/triggers/readiness-webhook.trigger.yaml +11 -0
- package/package.json +9 -1
- package/skills/stageflow/references/control-surface.md +1 -1
- package/skills/stageflow-author/references/catalog-write-conventions.md +2 -2
- package/skills/stageflow-run/SKILL.md +1 -1
- package/skills/stageflow-run/references/mcp-call.md +1 -1
- package/skills/stageflow-setup/SKILL.md +1 -1
- package/dist/ui/assets/index-59cjF0OA.js +0 -133
package/dist/cli/runCommand.js
CHANGED
|
@@ -2,7 +2,8 @@ import { readFile } from "node:fs/promises";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { parse as parseYaml } from "yaml";
|
|
4
4
|
import { coerceTaskFile } from "../config/loadTask.js";
|
|
5
|
-
import { relativizeLocalPathForNetwork } from "../config/catalogRelativePath.js";
|
|
5
|
+
import { isInsideProjectRoot, relativizeLocalPathForNetwork, } from "../config/catalogRelativePath.js";
|
|
6
|
+
import { resolveCliProjectRootLocal } from "./resolveCliProjectRoot.js";
|
|
6
7
|
import { PipelinePreflightError, PipelineValidationError } from "../runtime/pipelineRunner.js";
|
|
7
8
|
import { ensureGlobalService, hostBaseUrl, } from "../server/ensureGlobalService.js";
|
|
8
9
|
import { httpEnsureProject, httpStartRun, httpStoreReader } from "./hostClient.js";
|
|
@@ -10,7 +11,7 @@ import { reportCliRun, writeQueuedAdmissionLine, } from "./runOutput.js";
|
|
|
10
11
|
import { resolveCiIdentity } from "./ciIdentity.js";
|
|
11
12
|
import { exitCodeForValidation, formatValidationHuman, formatValidationJson, } from "./validateOutput.js";
|
|
12
13
|
export const RUN_USAGE = `Usage:
|
|
13
|
-
sf run --task <path> --pipeline <path> [--checkout <path>] [--repository <owner/repo>] [--ref <ref>] [--json] [--include stages] [--skip-gates] [--git-sha <sha>] [--ci-pr-url <url>] [--ci-job-url <url>] [--operator-cwd <path>] [--operator-agent-dir <path>]`;
|
|
14
|
+
sf run --task <path> --pipeline <path> [--project-root <id-or-path>] [--checkout <path>] [--repository <owner/repo>] [--ref <ref>] [--json] [--include stages] [--skip-gates] [--git-sha <sha>] [--ci-pr-url <url>] [--ci-job-url <url>] [--operator-cwd <path>] [--operator-agent-dir <path>]`;
|
|
14
15
|
const defaultIo = {
|
|
15
16
|
log: (line) => console.log(line),
|
|
16
17
|
error: (line) => console.error(line),
|
|
@@ -32,6 +33,7 @@ function parseRunArgs(args) {
|
|
|
32
33
|
let ciJobUrl;
|
|
33
34
|
let operatorCwd;
|
|
34
35
|
let operatorAgentDir;
|
|
36
|
+
let projectRoot;
|
|
35
37
|
let json = false;
|
|
36
38
|
let includeStages = false;
|
|
37
39
|
let skipGates = false;
|
|
@@ -111,6 +113,13 @@ function parseRunArgs(args) {
|
|
|
111
113
|
}
|
|
112
114
|
operatorAgentDir = value;
|
|
113
115
|
}
|
|
116
|
+
else if (arg === "--project-root") {
|
|
117
|
+
const value = args[++i];
|
|
118
|
+
if (value === undefined || value.length === 0) {
|
|
119
|
+
throw new Error("Missing value for --project-root");
|
|
120
|
+
}
|
|
121
|
+
projectRoot = value;
|
|
122
|
+
}
|
|
114
123
|
else if (arg === "--json") {
|
|
115
124
|
json = true;
|
|
116
125
|
}
|
|
@@ -151,8 +160,16 @@ function parseRunArgs(args) {
|
|
|
151
160
|
ciJobUrl,
|
|
152
161
|
operatorCwd,
|
|
153
162
|
operatorAgentDir,
|
|
163
|
+
projectRoot,
|
|
154
164
|
};
|
|
155
165
|
}
|
|
166
|
+
function resolvePathUnderCliRoot(rootPath, inputPath, label) {
|
|
167
|
+
const abs = path.resolve(rootPath, inputPath);
|
|
168
|
+
if (!isInsideProjectRoot(rootPath, abs)) {
|
|
169
|
+
throw new Error(`${label} ${abs} is outside project root ${rootPath}`);
|
|
170
|
+
}
|
|
171
|
+
return path.relative(rootPath, abs).replace(/\\/g, "/") || ".";
|
|
172
|
+
}
|
|
156
173
|
async function loadTaskWithBindingOverrides(taskPath, cwd, overrides) {
|
|
157
174
|
const absolute = path.resolve(cwd, taskPath);
|
|
158
175
|
const yamlText = await readFile(absolute, "utf8");
|
|
@@ -167,7 +184,7 @@ async function loadTaskWithBindingOverrides(taskPath, cwd, overrides) {
|
|
|
167
184
|
task.ref = overrides.ref;
|
|
168
185
|
return task;
|
|
169
186
|
}
|
|
170
|
-
function defaultStartRun(cwd, base, ensureService) {
|
|
187
|
+
function defaultStartRun(cwd, base, ensureService, cliProjectRoot) {
|
|
171
188
|
return async (input) => {
|
|
172
189
|
const ensured = await ensureService();
|
|
173
190
|
if (!ensured.ok) {
|
|
@@ -180,20 +197,34 @@ function defaultStartRun(cwd, base, ensureService) {
|
|
|
180
197
|
: {}),
|
|
181
198
|
};
|
|
182
199
|
}
|
|
183
|
-
|
|
200
|
+
let pipelineRef;
|
|
184
201
|
let task = input.task;
|
|
185
|
-
let projectRoot
|
|
186
|
-
if (
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
202
|
+
let projectRoot;
|
|
203
|
+
if (cliProjectRoot) {
|
|
204
|
+
pipelineRef = {
|
|
205
|
+
path: resolvePathUnderCliRoot(cliProjectRoot.rootPath, input.pipeline, "Pipeline"),
|
|
206
|
+
project_root: cliProjectRoot.wireId,
|
|
207
|
+
};
|
|
208
|
+
projectRoot = cliProjectRoot.wireId;
|
|
209
|
+
if (typeof input.task === "string") {
|
|
210
|
+
task = resolvePathUnderCliRoot(cliProjectRoot.rootPath, input.task, "Task");
|
|
192
211
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
pipelineRef = relativizeLocalPathForNetwork(cwd, input.pipeline);
|
|
215
|
+
projectRoot = pipelineRef.project_root;
|
|
216
|
+
if (typeof input.task === "string") {
|
|
217
|
+
const absTask = path.resolve(cwd, input.task);
|
|
218
|
+
const cwdAbs = path.resolve(cwd);
|
|
219
|
+
const relTask = path.relative(cwdAbs, absTask);
|
|
220
|
+
if (relTask.startsWith("..") || path.isAbsolute(relTask)) {
|
|
221
|
+
task = await loadTaskWithBindingOverrides(input.task, cwd, {});
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
const taskRef = relativizeLocalPathForNetwork(cwd, input.task);
|
|
225
|
+
task = taskRef.path;
|
|
226
|
+
projectRoot = taskRef.project_root;
|
|
227
|
+
}
|
|
197
228
|
}
|
|
198
229
|
}
|
|
199
230
|
const ensuredProject = await httpEnsureProject(base, projectRoot);
|
|
@@ -253,8 +284,18 @@ export async function runRunCommand(args, options = {}) {
|
|
|
253
284
|
if (parsed.operatorCwd !== undefined || parsed.operatorAgentDir !== undefined) {
|
|
254
285
|
out.error("warning: --operator-cwd/--operator-agent-dir have no effect on `sf run` now that pipelines execute in the shared global Stageflow service; set STAGEFLOW_OPERATOR_CWD/STAGEFLOW_OPERATOR_AGENT_DIR before that service first starts instead.");
|
|
255
286
|
}
|
|
287
|
+
let cliProjectRoot;
|
|
288
|
+
if (parsed.projectRoot !== undefined) {
|
|
289
|
+
const local = resolveCliProjectRootLocal(parsed.projectRoot);
|
|
290
|
+
if (!local) {
|
|
291
|
+
out.error(`Unknown project_root: ${parsed.projectRoot.trim()}`);
|
|
292
|
+
out.error(RUN_USAGE);
|
|
293
|
+
return 1;
|
|
294
|
+
}
|
|
295
|
+
cliProjectRoot = local;
|
|
296
|
+
}
|
|
256
297
|
const startRun = options.startRun ??
|
|
257
|
-
defaultStartRun(cwd, base, options.ensureService ?? (() => ensureGlobalService()));
|
|
298
|
+
defaultStartRun(cwd, base, options.ensureService ?? (() => ensureGlobalService()), cliProjectRoot);
|
|
258
299
|
const identity = resolveCiIdentity({
|
|
259
300
|
flags: {
|
|
260
301
|
gitSha: parsed.gitSha,
|
|
@@ -266,8 +307,9 @@ export async function runRunCommand(args, options = {}) {
|
|
|
266
307
|
const store = options.store ?? (parsed.includeStages ? httpStoreReader(base) : undefined);
|
|
267
308
|
try {
|
|
268
309
|
const hasBindingOverride = parsed.repository !== undefined || parsed.ref !== undefined;
|
|
310
|
+
const taskLoadRoot = cliProjectRoot?.rootPath ?? cwd;
|
|
269
311
|
const taskInput = hasBindingOverride
|
|
270
|
-
? await loadTaskWithBindingOverrides(parsed.task,
|
|
312
|
+
? await loadTaskWithBindingOverrides(parsed.task, taskLoadRoot, {
|
|
271
313
|
repository: parsed.repository,
|
|
272
314
|
ref: parsed.ref,
|
|
273
315
|
})
|
|
@@ -5,6 +5,26 @@ export type SkillsCommandIo = {
|
|
|
5
5
|
fetch: typeof globalThis.fetch;
|
|
6
6
|
runDoctor: (scriptPath: string, cwd: string) => number;
|
|
7
7
|
};
|
|
8
|
+
export type InstallProjectSkillInput = {
|
|
9
|
+
projectRoot: string;
|
|
10
|
+
fromPath?: string;
|
|
11
|
+
fromZip?: string;
|
|
12
|
+
zipBytes?: Uint8Array;
|
|
13
|
+
skillName?: string;
|
|
14
|
+
checksum?: string;
|
|
15
|
+
io?: Partial<SkillsCommandIo>;
|
|
16
|
+
};
|
|
17
|
+
export type InstallProjectSkillResult = {
|
|
18
|
+
ok: true;
|
|
19
|
+
skillName: string;
|
|
20
|
+
destPath: string;
|
|
21
|
+
message: string;
|
|
22
|
+
} | {
|
|
23
|
+
ok: false;
|
|
24
|
+
error: string;
|
|
25
|
+
doctorFailed?: boolean;
|
|
26
|
+
};
|
|
27
|
+
export declare function installProjectSkill(input: InstallProjectSkillInput): Promise<InstallProjectSkillResult>;
|
|
8
28
|
export declare function runSkillsCommand(args: string[], options?: {
|
|
9
29
|
cwd?: string;
|
|
10
30
|
projectRoot?: string;
|
|
@@ -291,14 +291,18 @@ async function findSkillRootBySkillMd(dir) {
|
|
|
291
291
|
}
|
|
292
292
|
return undefined;
|
|
293
293
|
}
|
|
294
|
-
async function resolveInstallSource(
|
|
295
|
-
const hasPath =
|
|
296
|
-
const hasZip =
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
294
|
+
async function resolveInstallSource(input, io) {
|
|
295
|
+
const hasPath = input.fromPath !== undefined;
|
|
296
|
+
const hasZip = input.fromZip !== undefined;
|
|
297
|
+
const hasZipBytes = input.zipBytes !== undefined;
|
|
298
|
+
const sourceCount = Number(hasPath) + Number(hasZip) + Number(hasZipBytes);
|
|
299
|
+
if (sourceCount !== 1) {
|
|
300
|
+
throw new Error(hasZipBytes
|
|
301
|
+
? "specify exactly one of fromPath, fromZip, or zipBytes"
|
|
302
|
+
: "specify exactly one of --from-path or --from-zip");
|
|
303
|
+
}
|
|
304
|
+
if (input.fromPath !== undefined) {
|
|
305
|
+
const sourceRoot = path.resolve(input.fromPath);
|
|
302
306
|
try {
|
|
303
307
|
const sourceStat = await stat(sourceRoot);
|
|
304
308
|
if (!sourceStat.isDirectory()) {
|
|
@@ -308,13 +312,21 @@ async function resolveInstallSource(parsed, io) {
|
|
|
308
312
|
catch {
|
|
309
313
|
throw new Error("source path not found");
|
|
310
314
|
}
|
|
311
|
-
const skillName =
|
|
315
|
+
const skillName = input.skillName ?? inferSkillNameFromPath(input.fromPath);
|
|
312
316
|
return { sourceRoot, skillName };
|
|
313
317
|
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
if (
|
|
317
|
-
|
|
318
|
+
let zipBytes;
|
|
319
|
+
let inferredZipName;
|
|
320
|
+
if (input.zipBytes !== undefined) {
|
|
321
|
+
zipBytes = Buffer.from(input.zipBytes);
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
const zipRef = input.fromZip;
|
|
325
|
+
zipBytes = await resolveZipBytes(zipRef, io);
|
|
326
|
+
inferredZipName = inferSkillNameFromZipRef(zipRef);
|
|
327
|
+
}
|
|
328
|
+
if (input.checksum !== undefined) {
|
|
329
|
+
const expected = parseChecksum(input.checksum);
|
|
318
330
|
const actual = sha256Hex(zipBytes);
|
|
319
331
|
if (actual !== expected) {
|
|
320
332
|
throw new Error("checksum mismatch");
|
|
@@ -322,8 +334,9 @@ async function resolveInstallSource(parsed, io) {
|
|
|
322
334
|
}
|
|
323
335
|
const extractDir = await mkdtemp(path.join(tmpdir(), "sf-skill-zip-"));
|
|
324
336
|
await extractZipBuffer(zipBytes, extractDir);
|
|
325
|
-
const
|
|
326
|
-
const sourceRoot = await findSkillRoot(extractDir,
|
|
337
|
+
const lookupName = input.skillName ?? inferredZipName ?? "skill";
|
|
338
|
+
const sourceRoot = await findSkillRoot(extractDir, lookupName);
|
|
339
|
+
const skillName = input.skillName ?? inferredZipName ?? path.basename(sourceRoot);
|
|
327
340
|
return {
|
|
328
341
|
sourceRoot,
|
|
329
342
|
skillName,
|
|
@@ -364,24 +377,46 @@ async function listSkills(projectRoot, io) {
|
|
|
364
377
|
io.log(`${name}\t${version}\tbin/${name}.mjs`);
|
|
365
378
|
}
|
|
366
379
|
}
|
|
367
|
-
async function
|
|
368
|
-
const
|
|
380
|
+
export async function installProjectSkill(input) {
|
|
381
|
+
const io = { ...defaultIo, ...input.io };
|
|
369
382
|
try {
|
|
370
|
-
const
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
383
|
+
const resolved = await resolveInstallSource({
|
|
384
|
+
fromPath: input.fromPath,
|
|
385
|
+
fromZip: input.fromZip,
|
|
386
|
+
zipBytes: input.zipBytes,
|
|
387
|
+
skillName: input.skillName,
|
|
388
|
+
checksum: input.checksum,
|
|
389
|
+
}, io);
|
|
390
|
+
try {
|
|
391
|
+
const destRoot = path.join(skillsDirForRoot(input.projectRoot), resolved.skillName);
|
|
392
|
+
await copySkillTree(resolved.sourceRoot, destRoot);
|
|
393
|
+
const doctorScript = path.join(destRoot, "bin", `${resolved.skillName}.mjs`);
|
|
394
|
+
if (await pathExists(doctorScript)) {
|
|
395
|
+
const doctorCode = io.runDoctor(doctorScript, input.projectRoot);
|
|
396
|
+
if (doctorCode !== 0) {
|
|
397
|
+
io.error("skill doctor failed");
|
|
398
|
+
return { ok: false, error: "skill doctor failed", doctorFailed: true };
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
const message = `Installed skill ${resolved.skillName} to ${destRoot}`;
|
|
402
|
+
io.log(message);
|
|
403
|
+
return {
|
|
404
|
+
ok: true,
|
|
405
|
+
skillName: resolved.skillName,
|
|
406
|
+
destPath: destRoot,
|
|
407
|
+
message,
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
finally {
|
|
411
|
+
if (resolved.cleanup) {
|
|
412
|
+
await resolved.cleanup();
|
|
413
|
+
}
|
|
377
414
|
}
|
|
378
|
-
io.log(`Installed skill ${resolved.skillName} to ${destRoot}`);
|
|
379
|
-
return 0;
|
|
380
415
|
}
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
}
|
|
416
|
+
catch (err) {
|
|
417
|
+
const error = err instanceof Error ? err.message : String(err);
|
|
418
|
+
io.error(error);
|
|
419
|
+
return { ok: false, error };
|
|
385
420
|
}
|
|
386
421
|
}
|
|
387
422
|
export async function runSkillsCommand(args, options = {}) {
|
|
@@ -402,7 +437,15 @@ export async function runSkillsCommand(args, options = {}) {
|
|
|
402
437
|
await listSkills(projectRoot, io);
|
|
403
438
|
return 0;
|
|
404
439
|
}
|
|
405
|
-
|
|
440
|
+
const result = await installProjectSkill({
|
|
441
|
+
projectRoot,
|
|
442
|
+
fromPath: parsed.fromPath,
|
|
443
|
+
fromZip: parsed.fromZip,
|
|
444
|
+
skillName: parsed.skillName,
|
|
445
|
+
checksum: parsed.checksum,
|
|
446
|
+
io,
|
|
447
|
+
});
|
|
448
|
+
return result.ok ? 0 : 1;
|
|
406
449
|
}
|
|
407
450
|
catch (err) {
|
|
408
451
|
io.error(err instanceof Error ? err.message : String(err));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { validateCatalog as defaultValidateCatalog, type ValidationResult } from "../config/validateCatalog.js";
|
|
2
|
-
export declare const VALIDATE_USAGE = "Usage:\n sf validate [--pipeline <path>] [--task <path>] [--trigger <path>] [--strict] [--json]\n\n With no flags, validates all pipelines and tasks declared in stageflow.yaml (manifest-all).\n --pipeline validates one pipeline file (includes uses:/include: transitively).\n --task validates one task file.\n --trigger validates one trigger file, including its pipeline/task refs.";
|
|
2
|
+
export declare const VALIDATE_USAGE = "Usage:\n sf validate [--project-root <id-or-path>] [--pipeline <path>] [--task <path>] [--trigger <path>] [--strict] [--json]\n\n With no flags, validates all pipelines and tasks declared in stageflow.yaml (manifest-all).\n --pipeline validates one pipeline file (includes uses:/include: transitively).\n --task validates one task file.\n --trigger validates one trigger file, including its pipeline/task refs.";
|
|
3
3
|
export type ValidateCommandIo = {
|
|
4
4
|
log: (line: string) => void;
|
|
5
5
|
error: (line: string) => void;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { validateCatalog as defaultValidateCatalog, } from "../config/validateCatalog.js";
|
|
2
2
|
import { exitCodeForValidation, formatValidationHuman, formatValidationJson, } from "./validateOutput.js";
|
|
3
|
+
import { resolveCliProjectRootLocal } from "./resolveCliProjectRoot.js";
|
|
3
4
|
export const VALIDATE_USAGE = `Usage:
|
|
4
|
-
sf validate [--pipeline <path>] [--task <path>] [--trigger <path>] [--strict] [--json]
|
|
5
|
+
sf validate [--project-root <id-or-path>] [--pipeline <path>] [--task <path>] [--trigger <path>] [--strict] [--json]
|
|
5
6
|
|
|
6
7
|
With no flags, validates all pipelines and tasks declared in stageflow.yaml (manifest-all).
|
|
7
8
|
--pipeline validates one pipeline file (includes uses:/include: transitively).
|
|
@@ -18,6 +19,7 @@ function parseValidateArgs(args) {
|
|
|
18
19
|
if (args[0] === "--help" || args[0] === "-h") {
|
|
19
20
|
return { help: true, strict: false, json: false };
|
|
20
21
|
}
|
|
22
|
+
let projectRoot;
|
|
21
23
|
let pipeline;
|
|
22
24
|
let task;
|
|
23
25
|
let trigger;
|
|
@@ -29,6 +31,13 @@ function parseValidateArgs(args) {
|
|
|
29
31
|
if (arg === "--help" || arg === "-h") {
|
|
30
32
|
help = true;
|
|
31
33
|
}
|
|
34
|
+
else if (arg === "--project-root") {
|
|
35
|
+
const value = args[++i];
|
|
36
|
+
if (value === undefined || value.length === 0) {
|
|
37
|
+
throw new Error("Missing value for --project-root");
|
|
38
|
+
}
|
|
39
|
+
projectRoot = value;
|
|
40
|
+
}
|
|
32
41
|
else if (arg === "--pipeline") {
|
|
33
42
|
const value = args[++i];
|
|
34
43
|
if (value === undefined || value.length === 0) {
|
|
@@ -67,11 +76,10 @@ function parseValidateArgs(args) {
|
|
|
67
76
|
if (scopedFlagCount > 1) {
|
|
68
77
|
throw new Error("Use at most one of --pipeline, --task, or --trigger");
|
|
69
78
|
}
|
|
70
|
-
return { help, pipeline, task, trigger, strict, json };
|
|
79
|
+
return { help, projectRoot, pipeline, task, trigger, strict, json };
|
|
71
80
|
}
|
|
72
81
|
export async function runValidateCommand(args, options = {}) {
|
|
73
|
-
const
|
|
74
|
-
const projectRoot = options.projectRoot ?? cwd;
|
|
82
|
+
const shellCwd = options.cwd ?? process.cwd();
|
|
75
83
|
const out = { ...defaultIo, ...options.io };
|
|
76
84
|
const validateCatalogFn = options.validateCatalog ?? defaultValidateCatalog;
|
|
77
85
|
try {
|
|
@@ -80,6 +88,16 @@ export async function runValidateCommand(args, options = {}) {
|
|
|
80
88
|
out.error(VALIDATE_USAGE);
|
|
81
89
|
return 0;
|
|
82
90
|
}
|
|
91
|
+
let cwd = shellCwd;
|
|
92
|
+
let projectRoot = options.projectRoot ?? shellCwd;
|
|
93
|
+
if (parsed.projectRoot !== undefined) {
|
|
94
|
+
const resolved = resolveCliProjectRootLocal(parsed.projectRoot);
|
|
95
|
+
if (!resolved) {
|
|
96
|
+
throw new Error(`Unknown project_root: ${parsed.projectRoot.trim()}`);
|
|
97
|
+
}
|
|
98
|
+
cwd = resolved.rootPath;
|
|
99
|
+
projectRoot = resolved.rootPath;
|
|
100
|
+
}
|
|
83
101
|
const scope = parsed.pipeline
|
|
84
102
|
? "pipeline"
|
|
85
103
|
: parsed.task
|
package/dist/cli.js
CHANGED
|
@@ -4,7 +4,7 @@ import { A2A_USAGE, runA2aCommand } from "./cli/a2aCommand.js";
|
|
|
4
4
|
import { realpathSync } from "node:fs";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
|
-
import {
|
|
7
|
+
import { globalStageBackendFromManifest, resolveStagePort } from "./agent/resolveStagePort.js";
|
|
8
8
|
import { BROWSER_USAGE, runBrowserCommand } from "./cli/browserCommand.js";
|
|
9
9
|
import { ARTIFACT_USAGE, runArtifactCommand } from "./cli/artifactCommand.js";
|
|
10
10
|
import { ENVELOPE_USAGE, runEnvelopeCommand, } from "./cli/envelopeCommand.js";
|
|
@@ -503,7 +503,7 @@ async function main(argv) {
|
|
|
503
503
|
if (parsed.command === "browser") {
|
|
504
504
|
return runBrowserCommand(argv.slice(3));
|
|
505
505
|
}
|
|
506
|
-
const globalAgent =
|
|
506
|
+
const globalAgent = globalStageBackendFromManifest(ctx.manifest);
|
|
507
507
|
if (parsed.command === "ui") {
|
|
508
508
|
const listenHost = resolveListenHost({ flag: parsed.host });
|
|
509
509
|
const tokens = loadControlTokens();
|
|
@@ -512,7 +512,7 @@ async function main(argv) {
|
|
|
512
512
|
mcpStateless: parsed.mcpStateless,
|
|
513
513
|
});
|
|
514
514
|
const host = await startUiServer({
|
|
515
|
-
agent:
|
|
515
|
+
agent: resolveStagePort({ global: globalAgent }),
|
|
516
516
|
cwd: ctx.invocationCwd,
|
|
517
517
|
rootDir: ctx.projectRoot,
|
|
518
518
|
port: parsed.port,
|
|
@@ -547,7 +547,7 @@ async function main(argv) {
|
|
|
547
547
|
mcpStateless: parsed.mcpStateless,
|
|
548
548
|
});
|
|
549
549
|
const host = await startMcpServer({
|
|
550
|
-
agent:
|
|
550
|
+
agent: resolveStagePort({ global: globalAgent }),
|
|
551
551
|
cwd: ctx.invocationCwd,
|
|
552
552
|
rootDir: ctx.projectRoot,
|
|
553
553
|
port: parsed.port,
|
|
@@ -22,6 +22,12 @@ function mapStageListing(stage, source, projectRoot) {
|
|
|
22
22
|
else if (source?.kind === "file") {
|
|
23
23
|
listing.uses_path = repoRelPath(projectRoot, source.path);
|
|
24
24
|
}
|
|
25
|
+
if (typeof stage.model === "string" && stage.model.trim() !== "") {
|
|
26
|
+
listing.model = stage.model;
|
|
27
|
+
}
|
|
28
|
+
if (typeof stage.skill === "string" && stage.skill.trim() !== "") {
|
|
29
|
+
listing.skill = stage.skill;
|
|
30
|
+
}
|
|
25
31
|
return listing;
|
|
26
32
|
}
|
|
27
33
|
function bakedModels() {
|
|
@@ -37,6 +37,10 @@ export declare function catalogPathErrorBody(err: CatalogPathError): {
|
|
|
37
37
|
* otherwise require explicit — no invent.
|
|
38
38
|
*/
|
|
39
39
|
export declare function selectCatalogRootForStart(roots: CatalogRoot[], projectRoot?: string): CatalogRoot;
|
|
40
|
+
export declare function resolveDefaultWriteRoot(options: ResolveCatalogRootsOptions, projectRoot?: string): Promise<{
|
|
41
|
+
roots: CatalogRoot[];
|
|
42
|
+
wireRoot: CatalogRoot;
|
|
43
|
+
}>;
|
|
40
44
|
/**
|
|
41
45
|
* Shared helper: resolveCatalogRoots → selectCatalogRootForStart.
|
|
42
46
|
* All network-surface start-input call sites use this to avoid the hand-copy sequence.
|
|
@@ -82,11 +82,43 @@ export function selectCatalogRootForStart(roots, projectRoot) {
|
|
|
82
82
|
if (roots.length === 1) {
|
|
83
83
|
return roots[0];
|
|
84
84
|
}
|
|
85
|
-
const
|
|
86
|
-
if (
|
|
87
|
-
return
|
|
85
|
+
const registeredOnly = roots.filter((r) => r.kind === "registered");
|
|
86
|
+
if (registeredOnly.length === 1) {
|
|
87
|
+
return registeredOnly[0];
|
|
88
88
|
}
|
|
89
|
-
|
|
89
|
+
const nonSeeded = roots.filter((r) => r.kind !== "seeded");
|
|
90
|
+
if (nonSeeded.length === 1) {
|
|
91
|
+
return nonSeeded[0];
|
|
92
|
+
}
|
|
93
|
+
const ids = roots.map((r) => r.project_root).join(", ");
|
|
94
|
+
throw new CatalogPathError(`project_root is required when multiple catalog roots are configured (${ids})`, "unknown_project_root", registered);
|
|
95
|
+
}
|
|
96
|
+
function workspaceRoot(roots) {
|
|
97
|
+
return roots.find((r) => r.kind === "workspace");
|
|
98
|
+
}
|
|
99
|
+
export async function resolveDefaultWriteRoot(options, projectRoot) {
|
|
100
|
+
const roots = await resolveCatalogRoots(options);
|
|
101
|
+
const registered = roots.map((r) => r.project_root);
|
|
102
|
+
if (projectRoot !== undefined) {
|
|
103
|
+
const found = findCatalogRoot(roots, projectRoot);
|
|
104
|
+
if (found === undefined) {
|
|
105
|
+
throw new CatalogPathError(`Unknown project_root: ${projectRoot}`, "unknown_project_root", registered);
|
|
106
|
+
}
|
|
107
|
+
if (found.read_only) {
|
|
108
|
+
throw new CatalogPathError(`Catalog root ${found.project_root} is read-only`, "catalog_root_read_only", registered);
|
|
109
|
+
}
|
|
110
|
+
if (found.kind === "workspace" && found.available === false) {
|
|
111
|
+
throw new CatalogPathError(found.unavailable_reason ??
|
|
112
|
+
`Workspace catalog is not writable (${found.path})`, "unknown_project_root", registered);
|
|
113
|
+
}
|
|
114
|
+
return { roots, wireRoot: found };
|
|
115
|
+
}
|
|
116
|
+
const ws = workspaceRoot(roots);
|
|
117
|
+
if (ws === undefined || ws.available === false) {
|
|
118
|
+
throw new CatalogPathError(ws?.unavailable_reason ??
|
|
119
|
+
"Workspace catalog is unavailable; set project_root explicitly", "unknown_project_root", registered);
|
|
120
|
+
}
|
|
121
|
+
return { roots, wireRoot: ws };
|
|
90
122
|
}
|
|
91
123
|
/**
|
|
92
124
|
* Shared helper: resolveCatalogRoots → selectCatalogRootForStart.
|
|
@@ -102,11 +134,7 @@ export async function resolveCatalogStartInput(options, projectRoot) {
|
|
|
102
134
|
* Used by write surfaces (POST /api/stages, POST /api/pipelines).
|
|
103
135
|
*/
|
|
104
136
|
export async function resolveWritableCatalogRoot(options, projectRoot) {
|
|
105
|
-
|
|
106
|
-
if (wireRoot.read_only) {
|
|
107
|
-
throw new CatalogPathError(`Catalog root ${wireRoot.project_root} is read-only`, "catalog_root_read_only", roots.map((r) => r.project_root));
|
|
108
|
-
}
|
|
109
|
-
return { roots, wireRoot };
|
|
137
|
+
return resolveDefaultWriteRoot(options, projectRoot);
|
|
110
138
|
}
|
|
111
139
|
/**
|
|
112
140
|
* Local CLI control: turn a cwd-resolved filesystem path into a catalog-relative
|
|
@@ -41,8 +41,12 @@ export function parseCreateStageBody(body) {
|
|
|
41
41
|
if ("payload_schema" in body) {
|
|
42
42
|
return { ok: false, status: 400, error: "payload_schema is not supported" };
|
|
43
43
|
}
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
let skill;
|
|
45
|
+
if (body.skill !== undefined) {
|
|
46
|
+
if (typeof body.skill !== "string" || body.skill.trim() === "") {
|
|
47
|
+
return { ok: false, status: 400, error: "skill must be a non-empty string" };
|
|
48
|
+
}
|
|
49
|
+
skill = body.skill.trim();
|
|
46
50
|
}
|
|
47
51
|
if (typeof body.pipeline_directory !== "string" || !body.pipeline_directory.trim()) {
|
|
48
52
|
return { ok: false, status: 400, error: "pipeline_directory is required" };
|
|
@@ -84,6 +88,7 @@ export function parseCreateStageBody(body) {
|
|
|
84
88
|
system_prompt: body.system_prompt,
|
|
85
89
|
...(model !== undefined ? { model } : {}),
|
|
86
90
|
...(gateKinds !== undefined ? { gate_kinds: gateKinds } : {}),
|
|
91
|
+
...(skill !== undefined ? { skill } : {}),
|
|
87
92
|
};
|
|
88
93
|
}
|
|
89
94
|
function formatInlineYamlScalar(value) {
|
|
@@ -122,6 +127,9 @@ export function stageConfigToYaml(stage) {
|
|
|
122
127
|
if (stage.model !== undefined && stage.model.length > 0) {
|
|
123
128
|
lines.push(`model: ${formatInlineYamlScalar(stage.model)}`);
|
|
124
129
|
}
|
|
130
|
+
if (stage.skill !== undefined && stage.skill.length > 0) {
|
|
131
|
+
lines.push(`skill: ${formatInlineYamlScalar(stage.skill)}`);
|
|
132
|
+
}
|
|
125
133
|
lines.push("io:");
|
|
126
134
|
lines.push(" input:");
|
|
127
135
|
lines.push(" schema:");
|
|
@@ -204,6 +212,7 @@ export async function createStage(projectRoot, input) {
|
|
|
204
212
|
system_prompt: input.system_prompt,
|
|
205
213
|
...(input.model !== undefined && input.model.length > 0 ? { model: input.model } : {}),
|
|
206
214
|
...(input.gate_kinds !== undefined ? { gate_kinds: input.gate_kinds } : {}),
|
|
215
|
+
...(input.skill !== undefined && input.skill.length > 0 ? { skill: input.skill } : {}),
|
|
207
216
|
}), "utf8");
|
|
208
217
|
}
|
|
209
218
|
catch (err) {
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { TaskDetail } from "./findTaskInCatalog.js";
|
|
2
|
+
export type CreateTaskInput = {
|
|
3
|
+
directory: string;
|
|
4
|
+
id: string;
|
|
5
|
+
goal: string;
|
|
6
|
+
context?: string;
|
|
7
|
+
constraints?: string;
|
|
8
|
+
checkout?: string;
|
|
9
|
+
repository?: string;
|
|
10
|
+
ref?: string;
|
|
11
|
+
};
|
|
12
|
+
export type CreateTaskParseError = {
|
|
13
|
+
ok: false;
|
|
14
|
+
status: 400;
|
|
15
|
+
error: string;
|
|
16
|
+
};
|
|
17
|
+
export type CreateTaskResult = {
|
|
18
|
+
ok: true;
|
|
19
|
+
task: TaskDetail;
|
|
20
|
+
} | {
|
|
21
|
+
ok: false;
|
|
22
|
+
status: 400 | 404 | 409 | 500 | 502;
|
|
23
|
+
error: string;
|
|
24
|
+
};
|
|
25
|
+
export declare function validateTaskId(id: string): string | null;
|
|
26
|
+
export declare function parseCreateTaskBody(body: unknown): CreateTaskInput | CreateTaskParseError;
|
|
27
|
+
export declare function resolveTaskDirectory(projectRoot: string, directory: string): string | null;
|
|
28
|
+
export declare function taskFieldsToYaml(fields: CreateTaskInput): string;
|
|
29
|
+
export declare function findTaskIdCollision(projectRoot: string, id: string, targetPath: string): Promise<string | null>;
|
|
30
|
+
export declare function createTask(rawProjectRoot: string, input: CreateTaskInput): Promise<CreateTaskResult>;
|