stageflow 0.23.0 → 0.27.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 +24 -5
- package/dist/a2a/configDiscovery.d.ts +9 -0
- package/dist/a2a/configDiscovery.js +18 -0
- package/dist/a2a/contracts.d.ts +94 -0
- package/dist/a2a/contracts.js +164 -0
- package/dist/a2a/limits.d.ts +14 -0
- package/dist/a2a/limits.js +29 -0
- package/dist/a2a/registry.d.ts +46 -0
- package/dist/a2a/registry.js +178 -0
- package/dist/a2a/server.d.ts +36 -0
- package/dist/a2a/server.js +344 -0
- package/dist/a2a/service.d.ts +97 -0
- package/dist/a2a/service.js +545 -0
- package/dist/a2a/store.d.ts +109 -0
- package/dist/a2a/store.js +202 -0
- package/dist/agent/activity.d.ts +3 -0
- package/dist/agent/bootProviderConfig.d.ts +21 -0
- package/dist/agent/bootProviderConfig.js +74 -0
- package/dist/agent/piAdapter.d.ts +9 -1
- package/dist/agent/piAdapter.js +58 -3
- package/dist/agent/piIsolatedMcp.d.ts +2 -0
- package/dist/agent/piIsolatedMcp.js +10 -2
- package/dist/agent/port.d.ts +6 -0
- package/dist/agent/streamLogRedact.d.ts +1 -1
- package/dist/agent/streamLogRedact.js +4 -11
- package/dist/cli/a2aCommand.d.ts +8 -0
- package/dist/cli/a2aCommand.js +131 -0
- package/dist/cli/artifactCommand.js +9 -16
- package/dist/cli/backupCommand.d.ts +9 -0
- package/dist/cli/backupCommand.js +111 -0
- package/dist/cli/debugRunCommand.d.ts +10 -0
- package/dist/cli/debugRunCommand.js +109 -0
- package/dist/cli/doctorCommand.d.ts +32 -0
- package/dist/cli/doctorCommand.js +453 -0
- package/dist/cli/envelopeCommand.js +9 -2
- package/dist/cli/exportAllCommand.d.ts +55 -0
- package/dist/cli/exportAllCommand.js +218 -0
- package/dist/cli/exportRunCommand.js +23 -21
- package/dist/cli/hostClient.d.ts +21 -3
- package/dist/cli/hostClient.js +93 -12
- package/dist/cli/initTemplates.d.ts +1 -1
- package/dist/cli/initTemplates.js +8 -1
- package/dist/cli/resolveSafeOutPath.d.ts +2 -0
- package/dist/cli/resolveSafeOutPath.js +40 -0
- package/dist/cli/restoreCommand.d.ts +10 -0
- package/dist/cli/restoreCommand.js +90 -0
- package/dist/cli/runCommand.d.ts +3 -2
- package/dist/cli/runCommand.js +93 -11
- package/dist/cli/runOutput.d.ts +4 -0
- package/dist/cli/runOutput.js +33 -7
- package/dist/cli/runStageCommand.d.ts +34 -0
- package/dist/cli/runStageCommand.js +426 -0
- package/dist/cli/runsCommand.d.ts +1 -1
- package/dist/cli/runsCommand.js +162 -8
- package/dist/cli.js +190 -30
- package/dist/config/catalogRelativePath.d.ts +62 -0
- package/dist/config/catalogRelativePath.js +118 -0
- package/dist/config/configOrigin.d.ts +27 -0
- package/dist/config/configOrigin.js +59 -0
- package/dist/config/hostConfig.d.ts +55 -0
- package/dist/config/hostConfig.js +333 -0
- package/dist/config/listSkills.d.ts +26 -0
- package/dist/config/listSkills.js +190 -3
- package/dist/config/loadOutcome.d.ts +1 -1
- package/dist/config/loadPipeline.js +23 -2
- package/dist/config/loadStage.js +18 -0
- package/dist/config/loadTask.d.ts +2 -0
- package/dist/config/loadTask.js +57 -18
- package/dist/config/materializeStageModels.js +5 -1
- package/dist/config/mergePipelineIncludes.d.ts +3 -0
- package/dist/config/mergePipelineIncludes.js +19 -0
- package/dist/config/migrateYaml.js +6 -11
- package/dist/config/multiProjectCatalog.d.ts +30 -0
- package/dist/config/multiProjectCatalog.js +142 -0
- package/dist/config/normalizePipelineStageEntry.js +20 -1
- package/dist/config/pipelineStageKeys.js +2 -0
- package/dist/config/resolveCatalogRoots.d.ts +27 -0
- package/dist/config/resolveCatalogRoots.js +76 -0
- package/dist/config/resolveModel.d.ts +7 -1
- package/dist/config/resolveModel.js +11 -1
- package/dist/config/resolveStageMcpServers.d.ts +9 -1
- package/dist/config/resolveStageMcpServers.js +36 -9
- package/dist/config/secretFromEnvOrFile.d.ts +9 -0
- package/dist/config/secretFromEnvOrFile.js +34 -0
- package/dist/config/seededCatalog.d.ts +11 -0
- package/dist/config/seededCatalog.js +29 -0
- package/dist/config/toolRequires.d.ts +24 -0
- package/dist/config/toolRequires.js +115 -0
- package/dist/config/validateCatalog.d.ts +5 -1
- package/dist/config/validateCatalog.js +140 -1
- package/dist/diagnostics/checks.d.ts +39 -0
- package/dist/diagnostics/checks.js +135 -0
- package/dist/errors/codes.d.ts +14 -0
- package/dist/errors/codes.js +59 -0
- package/dist/git/cache.d.ts +14 -0
- package/dist/git/cache.js +150 -0
- package/dist/git/credentials.d.ts +9 -0
- package/dist/git/credentials.js +88 -0
- package/dist/git/errors.d.ts +20 -0
- package/dist/git/errors.js +94 -0
- package/dist/git/exec.d.ts +16 -0
- package/dist/git/exec.js +135 -0
- package/dist/git/operations.d.ts +29 -0
- package/dist/git/operations.js +153 -0
- package/dist/git/version.d.ts +1 -0
- package/dist/git/version.js +10 -0
- package/dist/logging/audit.d.ts +16 -0
- package/dist/logging/audit.js +19 -0
- package/dist/logging/commonWords.d.ts +2 -0
- package/dist/logging/commonWords.js +13 -0
- package/dist/logging/logger.d.ts +49 -0
- package/dist/logging/logger.js +193 -0
- package/dist/logging/namedSecrets.d.ts +6 -0
- package/dist/logging/namedSecrets.js +58 -0
- package/dist/logging/redact.d.ts +13 -0
- package/dist/logging/redact.js +88 -0
- package/dist/mcp/catalogTools.js +591 -76
- package/dist/mcp/checkoutTools.d.ts +52 -0
- package/dist/mcp/checkoutTools.js +332 -0
- package/dist/mcp/controlTools.js +179 -5
- package/dist/mcp/deps.d.ts +1 -0
- package/dist/mcp/getStartedTool.d.ts +3 -0
- package/dist/mcp/getStartedTool.js +62 -0
- package/dist/mcp/readArtifact.d.ts +11 -0
- package/dist/mcp/readArtifact.js +46 -30
- package/dist/mcp/server.js +1 -0
- package/dist/mcp/tools.js +4 -0
- package/dist/net/proxy.d.ts +14 -0
- package/dist/net/proxy.js +78 -0
- package/dist/package-meta.d.ts +2 -1
- package/dist/package-meta.js +2 -1
- package/dist/preflight/bash.d.ts +8 -0
- package/dist/preflight/bash.js +34 -0
- package/dist/preflight/claudeRoot.d.ts +11 -0
- package/dist/preflight/claudeRoot.js +23 -0
- package/dist/preflight/mcpCommands.d.ts +8 -0
- package/dist/preflight/mcpCommands.js +36 -0
- package/dist/preflight/pipelinePreflight.d.ts +40 -0
- package/dist/preflight/pipelinePreflight.js +192 -0
- package/dist/preflight/tls.d.ts +6 -0
- package/dist/preflight/tls.js +18 -0
- package/dist/preflight/toolchain.d.ts +45 -0
- package/dist/preflight/toolchain.js +219 -0
- package/dist/project/findProjectRoot.js +3 -4
- package/dist/project/globalHome.d.ts +7 -0
- package/dist/project/globalHome.js +63 -2
- package/dist/project/resolveProjectContext.js +2 -2
- package/dist/project/resolveStageflowContext.js +2 -2
- package/dist/projection/projectRun.d.ts +2 -1
- package/dist/projection/projectRun.js +1 -0
- package/dist/runstore/assertTmpdir.d.ts +1 -0
- package/dist/runstore/assertTmpdir.js +21 -0
- package/dist/runstore/backup.d.ts +52 -0
- package/dist/runstore/backup.js +292 -0
- package/dist/runstore/createStore.d.ts +27 -0
- package/dist/runstore/createStore.js +75 -7
- package/dist/runstore/debugBundle.d.ts +60 -0
- package/dist/runstore/debugBundle.js +143 -0
- package/dist/runstore/diskUsage.d.ts +50 -0
- package/dist/runstore/diskUsage.js +214 -0
- package/dist/runstore/exportRunPayload.d.ts +8 -0
- package/dist/runstore/exportRunPayload.js +23 -0
- package/dist/runstore/normalizeCatalogPath.d.ts +1 -0
- package/dist/runstore/normalizeCatalogPath.js +10 -0
- package/dist/runstore/paths.d.ts +5 -0
- package/dist/runstore/paths.js +145 -1
- package/dist/runstore/port.d.ts +119 -8
- package/dist/runstore/port.js +8 -1
- package/dist/runstore/restore.d.ts +81 -0
- package/dist/runstore/restore.js +355 -0
- package/dist/runstore/retention.d.ts +27 -0
- package/dist/runstore/retention.js +74 -0
- package/dist/runstore/runManifest.d.ts +146 -0
- package/dist/runstore/runManifest.js +288 -0
- package/dist/runstore/runProjection.d.ts +3 -1
- package/dist/runstore/runProjection.js +63 -1
- package/dist/runstore/sqlite/SqliteRunStore.d.ts +37 -3
- package/dist/runstore/sqlite/SqliteRunStore.js +401 -227
- package/dist/runstore/sqlite/applyStorePragmas.d.ts +39 -0
- package/dist/runstore/sqlite/applyStorePragmas.js +145 -0
- package/dist/runstore/sqlite/migrations/001-baseline.d.ts +7 -0
- package/dist/runstore/sqlite/migrations/001-baseline.js +10 -0
- package/dist/runstore/sqlite/migrations/002-repository-binding.d.ts +7 -0
- package/dist/runstore/sqlite/migrations/002-repository-binding.js +29 -0
- package/dist/runstore/sqlite/migrations/003-run-lifecycle.d.ts +7 -0
- package/dist/runstore/sqlite/migrations/003-run-lifecycle.js +28 -0
- package/dist/runstore/sqlite/migrations/004-auto-resume-count.d.ts +7 -0
- package/dist/runstore/sqlite/migrations/004-auto-resume-count.js +19 -0
- package/dist/runstore/sqlite/migrations/005-config-origins.d.ts +7 -0
- package/dist/runstore/sqlite/migrations/005-config-origins.js +19 -0
- package/dist/runstore/sqlite/migrations/006-pipeline-body-and-caller.d.ts +7 -0
- package/dist/runstore/sqlite/migrations/006-pipeline-body-and-caller.js +28 -0
- package/dist/runstore/sqlite/migrations/007-projects-registry.d.ts +7 -0
- package/dist/runstore/sqlite/migrations/007-projects-registry.js +31 -0
- package/dist/runstore/sqlite/migrations/index.d.ts +21 -0
- package/dist/runstore/sqlite/migrations/index.js +72 -0
- package/dist/runstore/sqlite/schema.d.ts +20 -1
- package/dist/runstore/sqlite/schema.js +283 -1
- package/dist/runstore/sqlite/storeOpenError.d.ts +6 -0
- package/dist/runstore/sqlite/storeOpenError.js +11 -0
- package/dist/runstore/sqlite/storeSchemaError.d.ts +5 -0
- package/dist/runstore/sqlite/storeSchemaError.js +8 -0
- package/dist/runstore/stageExecution.js +3 -0
- package/dist/runstore/storeFilesystem.d.ts +32 -0
- package/dist/runstore/storeFilesystem.js +148 -0
- package/dist/runstore/submission.d.ts +11 -0
- package/dist/runstore/submission.js +7 -0
- package/dist/runstore/trackProjection.js +2 -0
- package/dist/runstore/workspaceLayout.d.ts +13 -0
- package/dist/runstore/workspaceLayout.js +76 -0
- package/dist/runtime/completionCheckRunner.d.ts +3 -0
- package/dist/runtime/completionCheckRunner.js +45 -7
- package/dist/runtime/containerLimits.d.ts +16 -0
- package/dist/runtime/containerLimits.js +84 -0
- package/dist/runtime/credentialMaterialisation.d.ts +28 -0
- package/dist/runtime/credentialMaterialisation.js +128 -0
- package/dist/runtime/gitCheckoutCapability.js +7 -13
- package/dist/runtime/pipelineRunner.d.ts +38 -1
- package/dist/runtime/pipelineRunner.js +179 -15
- package/dist/runtime/pipelineScheduler.d.ts +15 -0
- package/dist/runtime/pipelineScheduler.js +167 -42
- package/dist/runtime/reloadRunCatalog.js +12 -1
- package/dist/runtime/repositoryMaterialize.d.ts +47 -0
- package/dist/runtime/repositoryMaterialize.js +235 -0
- package/dist/runtime/resolveEnvelopeRef.d.ts +30 -0
- package/dist/runtime/resolveEnvelopeRef.js +79 -0
- package/dist/runtime/resumeTimedOut.d.ts +1 -1
- package/dist/runtime/resumeTimedOut.js +5 -2
- package/dist/runtime/runChangeBus.js +9 -0
- package/dist/runtime/runDeletion.d.ts +7 -0
- package/dist/runtime/runDeletion.js +37 -0
- package/dist/runtime/runManager.d.ts +179 -4
- package/dist/runtime/runManager.js +1644 -83
- package/dist/runtime/runRetentionSweep.d.ts +31 -0
- package/dist/runtime/runRetentionSweep.js +328 -0
- package/dist/runtime/runRetryCoordinator.d.ts +2 -0
- package/dist/runtime/runRetryCoordinator.js +19 -2
- package/dist/runtime/runSkills.d.ts +40 -0
- package/dist/runtime/runSkills.js +173 -0
- package/dist/runtime/stageAttemptBootstrap.d.ts +5 -1
- package/dist/runtime/stageAttemptBootstrap.js +195 -24
- package/dist/runtime/stageCacheEnv.d.ts +6 -0
- package/dist/runtime/stageCacheEnv.js +34 -0
- package/dist/runtime/stageConcurrency.d.ts +2 -1
- package/dist/runtime/stageConcurrency.js +4 -2
- package/dist/runtime/stageEnvironment.d.ts +38 -0
- package/dist/runtime/stageEnvironment.js +193 -0
- package/dist/runtime/stageProcessLauncher.d.ts +18 -0
- package/dist/runtime/stageProcessLauncher.js +194 -38
- package/dist/runtime/stageRecovery.d.ts +3 -1
- package/dist/runtime/stageRecovery.js +19 -4
- package/dist/runtime/stageRoots.d.ts +38 -1
- package/dist/runtime/stageRoots.js +118 -0
- package/dist/runtime/stageRunner.d.ts +1 -0
- package/dist/runtime/stageRunner.js +3 -1
- package/dist/runtime/stageSecretDecl.d.ts +9 -0
- package/dist/runtime/stageSecretDecl.js +102 -0
- package/dist/runtime/stageSecrets.d.ts +40 -0
- package/dist/runtime/stageSecrets.js +181 -0
- package/dist/runtime/stageWorker.d.ts +3 -2
- package/dist/runtime/stageWorker.js +58 -10
- package/dist/runtime/stageWorkerProtocol.d.ts +5 -0
- package/dist/runtime/stageWorkerProtocol.js +8 -0
- package/dist/runtime/startPayload.d.ts +32 -0
- package/dist/runtime/startPayload.js +59 -0
- package/dist/runtime/taskInput.js +14 -5
- package/dist/runtime/verifiedStageExecution.d.ts +1 -0
- package/dist/runtime/verifiedStageExecution.js +2 -1
- package/dist/runtime/workspaceBinding.d.ts +20 -0
- package/dist/runtime/workspaceBinding.js +60 -0
- package/dist/server/allowedHosts.d.ts +19 -0
- package/dist/server/allowedHosts.js +179 -0
- package/dist/server/bootstrap.d.ts +38 -2
- package/dist/server/bootstrap.js +219 -4
- package/dist/server/controlToken.d.ts +47 -0
- package/dist/server/controlToken.js +241 -0
- package/dist/server/createHttpHost.d.ts +11 -2
- package/dist/server/createHttpHost.js +109 -10
- package/dist/server/ensureGlobalService.d.ts +5 -1
- package/dist/server/ensureGlobalService.js +35 -1
- package/dist/server/healthSurfaces.d.ts +6 -0
- package/dist/server/healthSurfaces.js +98 -0
- package/dist/server/http.d.ts +12 -1
- package/dist/server/http.js +1085 -485
- package/dist/server/listenHost.d.ts +5 -0
- package/dist/server/listenHost.js +56 -0
- package/dist/server/mcpHost.d.ts +10 -1
- package/dist/server/mcpHost.js +36 -6
- package/dist/server/operatorResults.d.ts +2 -2
- package/dist/server/operatorResults.js +40 -29
- package/dist/server/requestAuthContext.d.ts +12 -0
- package/dist/server/requestAuthContext.js +21 -0
- package/dist/server/shutdown.d.ts +69 -0
- package/dist/server/shutdown.js +219 -0
- package/dist/types/pipeline.d.ts +7 -0
- package/dist/types/stage.d.ts +8 -0
- package/dist/types/task.d.ts +8 -0
- package/dist/ui/assets/index-B6hlSXXn.js +120 -0
- package/dist/ui/index.html +1 -1
- package/examples/README.md +98 -0
- package/examples/archify-on-pr/README.md +213 -0
- package/examples/archify-on-pr/archify-on-pr.pipeline.yaml +19 -0
- package/examples/archify-on-pr/archify-on-pr.task.yaml +19 -0
- package/examples/archify-on-pr/author-diagrams.yaml +106 -0
- package/examples/archify-on-pr/detect-changes.yaml +89 -0
- package/examples/ci-validate/README.md +35 -0
- package/examples/ci-validate/check.yaml +13 -0
- package/examples/ci-validate/ci-demo.pipeline.yaml +4 -0
- package/examples/ci-validate/validate.sh +5 -0
- package/examples/compliance-review-demo/README.md +125 -0
- package/examples/compliance-review-demo/compliance-review-demo.pipeline.yaml +29 -0
- package/examples/compliance-review-demo/connect-account.yaml +47 -0
- package/examples/compliance-review-demo/map-to-control.yaml +123 -0
- package/examples/compliance-review-demo/poll-bucket-config.yaml +103 -0
- package/examples/compliance-review-demo/publish-report.yaml +79 -0
- package/examples/compliance-review-demo/review-verdict.yaml +122 -0
- package/examples/compliance-review-demo/run-compliance-check.yaml +96 -0
- package/examples/compliance-review-demo/store-evidence.yaml +143 -0
- package/examples/conditional-fork/README.md +89 -0
- package/examples/conditional-fork/branch-a.yaml +13 -0
- package/examples/conditional-fork/branch-b.yaml +13 -0
- package/examples/conditional-fork/decide.yaml +35 -0
- package/examples/conditional-fork/fork-demo.pipeline.yaml +20 -0
- package/examples/conditional-fork/fork-demo.task.yaml +8 -0
- package/examples/context7-mcp/README.md +42 -0
- package/examples/context7-mcp/context7-mcp.pipeline.yaml +15 -0
- package/examples/context7-mcp/context7-mcp.task.yaml +4 -0
- package/examples/context7-mcp/fetch-docs.yaml +52 -0
- package/examples/context7-mcp/resolve-library.yaml +31 -0
- package/examples/context7-mcp/write-brief.yaml +52 -0
- package/examples/feature-loop/README.md +104 -0
- package/examples/feature-loop/address-feedback.yaml +148 -0
- package/examples/feature-loop/align.yaml +116 -0
- package/examples/feature-loop/decompose.yaml +86 -0
- package/examples/feature-loop/default-model-hierarchy.task.yaml +58 -0
- package/examples/feature-loop/feature-loop.pipeline.yaml +140 -0
- package/examples/feature-loop/feature-loop.task.yaml +25 -0
- package/examples/feature-loop/implement.yaml +128 -0
- package/examples/feature-loop/plan.yaml +111 -0
- package/examples/feature-loop/publish.yaml +167 -0
- package/examples/feature-loop/review.yaml +146 -0
- package/examples/feature-loop/verify.yaml +106 -0
- package/examples/feedback-loop/README.md +72 -0
- package/examples/feedback-loop/VERIFY.md +208 -0
- package/examples/feedback-loop/continue-only.task.yaml +4 -0
- package/examples/feedback-loop/exhaust-require-continue.task.yaml +6 -0
- package/examples/feedback-loop/exhaust-wait-human.task.yaml +11 -0
- package/examples/feedback-loop/feedback-loop-wait-human.pipeline.yaml +23 -0
- package/examples/feedback-loop/feedback-loop.pipeline.yaml +23 -0
- package/examples/feedback-loop/feedback-loop.task.yaml +4 -0
- package/examples/feedback-loop/implement.yaml +14 -0
- package/examples/feedback-loop/plan.yaml +14 -0
- package/examples/feedback-loop/review.yaml +15 -0
- package/examples/feedback-loop/send-back-once.task.yaml +6 -0
- package/examples/feedback-loop/submit.yaml +12 -0
- package/examples/generic-fan-in/README.md +151 -0
- package/examples/generic-fan-in/clarify.yaml +18 -0
- package/examples/generic-fan-in/generic-fan-in-accepted.pipeline.yaml +19 -0
- package/examples/generic-fan-in/generic-fan-in-accepted.task.yaml +8 -0
- package/examples/generic-fan-in/generic-fan-in.pipeline.yaml +18 -0
- package/examples/generic-fan-in/generic-fan-in.task.yaml +9 -0
- package/examples/generic-fan-in/research.yaml +45 -0
- package/examples/generic-fan-in/synthesize.yaml +66 -0
- package/examples/generic-fan-in/validation.yaml +45 -0
- package/examples/github-release/README.md +78 -0
- package/examples/github-release/draft-release-notes.yaml +64 -0
- package/examples/github-release/github-release.pipeline.yaml +11 -0
- package/examples/github-release/github-release.task.yaml +13 -0
- package/examples/github-release/publish-github-release.yaml +64 -0
- package/examples/hello-world/README.md +28 -0
- package/examples/hello-world/hello.pipeline.yaml +4 -0
- package/examples/hello-world/my-task.task.yaml +6 -0
- package/examples/hello-world/research.yaml +18 -0
- package/examples/mcp-hitl-tour/README.md +113 -0
- package/examples/mcp-hitl-tour/draft-angle.yaml +33 -0
- package/examples/mcp-hitl-tour/draft-short.yaml +32 -0
- package/examples/mcp-hitl-tour/emit-angles.yaml +45 -0
- package/examples/mcp-hitl-tour/gather.yaml +31 -0
- package/examples/mcp-hitl-tour/intake.yaml +62 -0
- package/examples/mcp-hitl-tour/mcp-hitl-tour-exhaust.task.yaml +13 -0
- package/examples/mcp-hitl-tour/mcp-hitl-tour.pipeline.yaml +54 -0
- package/examples/mcp-hitl-tour/mcp-hitl-tour.task.yaml +16 -0
- package/examples/mcp-hitl-tour/polish.yaml +33 -0
- package/examples/mcp-hitl-tour/review.yaml +17 -0
- package/examples/mcp-hitl-tour/ship.yaml +25 -0
- package/examples/oss-issue-contribution/README.md +218 -0
- package/examples/oss-issue-contribution/oss-address-review-feedback.yaml +117 -0
- package/examples/oss-issue-contribution/oss-approve-contribution.yaml +181 -0
- package/examples/oss-issue-contribution/oss-approve-plan.yaml +111 -0
- package/examples/oss-issue-contribution/oss-explain-fix.yaml +108 -0
- package/examples/oss-issue-contribution/oss-explain-issue.yaml +114 -0
- package/examples/oss-issue-contribution/oss-implement-source-fix.yaml +171 -0
- package/examples/oss-issue-contribution/oss-investigate-area.yaml +116 -0
- package/examples/oss-issue-contribution/oss-issue-contribution.pipeline.yaml +125 -0
- package/examples/oss-issue-contribution/oss-issue-intake.yaml +106 -0
- package/examples/oss-issue-contribution/oss-plan-investigation.yaml +112 -0
- package/examples/oss-issue-contribution/oss-plan-review.yaml +109 -0
- package/examples/oss-issue-contribution/oss-reproduce-issue.yaml +140 -0
- package/examples/oss-issue-contribution/oss-review-change.yaml +107 -0
- package/examples/oss-issue-contribution/oss-verify-fix.yaml +130 -0
- package/examples/oss-issue-contribution/oss-write-regression-test.yaml +135 -0
- package/examples/oss-issue-contribution/pi-7629.task.yaml +79 -0
- package/examples/oss-issue-contribution/pi-8919.task.yaml +75 -0
- package/examples/oss-issue-contribution/pydantic-ai-7971.task.yaml +53 -0
- package/examples/oss-quick-fix/README.md +65 -0
- package/examples/oss-quick-fix/implement-fix.yaml +84 -0
- package/examples/oss-quick-fix/oss-quick-fix.pipeline.yaml +35 -0
- package/examples/oss-quick-fix/oss-quick-fix.task.yaml +19 -0
- package/examples/oss-quick-fix/ship-fix.yaml +81 -0
- package/examples/oss-quick-fix/understand-issue.yaml +67 -0
- package/examples/oss-quick-fix/verify-fix.yaml +73 -0
- package/examples/plan-review/README.md +37 -0
- package/examples/plan-review/plan-review-followup.yaml +13 -0
- package/examples/plan-review/plan-review.pipeline.yaml +9 -0
- package/examples/plan-review/plan-review.task.yaml +9 -0
- package/examples/plan-review/plan-review.yaml +25 -0
- package/examples/playwright-mcp/README.md +39 -0
- package/examples/playwright-mcp/playwright-mcp.pipeline.yaml +5 -0
- package/examples/playwright-mcp/playwright-mcp.task.yaml +4 -0
- package/examples/playwright-mcp/screenshot.yaml +40 -0
- package/examples/retry-tour/README.md +75 -0
- package/examples/retry-tour/retry-tour.pipeline.yaml +122 -0
- package/examples/retry-tour/retry-tour.task.yaml +9 -0
- package/examples/route-if-tour/README.md +202 -0
- package/examples/route-if-tour/route-if-tour.pipeline.yaml +950 -0
- package/examples/route-if-tour/route-if-tour.task.yaml +4 -0
- package/examples/route-wiring-smoke-test/01-core-routing.pipeline.yaml +168 -0
- package/examples/route-wiring-smoke-test/02-on-gating.pipeline.yaml +44 -0
- package/examples/route-wiring-smoke-test/03-two-entry-points.pipeline.yaml +28 -0
- package/examples/route-wiring-smoke-test/04-entry-false-equivalent-to-omitted.pipeline.yaml +27 -0
- package/examples/route-wiring-smoke-test/05-fork-choice.pipeline.yaml +110 -0
- package/examples/route-wiring-smoke-test/06-fan-out-fan-in.pipeline.yaml +82 -0
- package/examples/route-wiring-smoke-test/07-loop-human-decision.pipeline.yaml +82 -0
- package/examples/route-wiring-smoke-test/08-skip-fallback-and-multi-on-gate.pipeline.yaml +77 -0
- package/examples/route-wiring-smoke-test/09-multi-loop-targets.pipeline.yaml +102 -0
- package/examples/route-wiring-smoke-test/10-uses-dialect-fork.pipeline.yaml +23 -0
- package/examples/route-wiring-smoke-test/11-sequential-io-handoff.pipeline.yaml +37 -0
- package/examples/route-wiring-smoke-test/12-complex-io-schemas.pipeline.yaml +138 -0
- package/examples/route-wiring-smoke-test/13-ref-io-handoff.pipeline.yaml +84 -0
- package/examples/route-wiring-smoke-test/14-if-eq-gating.pipeline.yaml +50 -0
- package/examples/route-wiring-smoke-test/15-if-all-gated.pipeline.yaml +37 -0
- package/examples/route-wiring-smoke-test/16-if-composition.pipeline.yaml +65 -0
- package/examples/route-wiring-smoke-test/17-if-join.pipeline.yaml +80 -0
- package/examples/route-wiring-smoke-test/README.md +377 -0
- package/examples/route-wiring-smoke-test/rejected/01-reject-legacy-needs.pipeline.yaml +26 -0
- package/examples/route-wiring-smoke-test/rejected/02-reject-legacy-fork.pipeline.yaml +25 -0
- package/examples/route-wiring-smoke-test/rejected/03-reject-legacy-feedback-loop.pipeline.yaml +30 -0
- package/examples/route-wiring-smoke-test/rejected/04-reject-missing-entry.pipeline.yaml +24 -0
- package/examples/route-wiring-smoke-test/rejected/05-reject-unreachable.pipeline.yaml +35 -0
- package/examples/route-wiring-smoke-test/rejected/06-reject-allow-none-without-route-select.pipeline.yaml +37 -0
- package/examples/route-wiring-smoke-test/rejected/07-reject-cycle.pipeline.yaml +27 -0
- package/examples/route-wiring-smoke-test/rejected/08-reject-loop-non-ancestor.pipeline.yaml +42 -0
- package/examples/route-wiring-smoke-test/rejected/09-reject-route-select-leaf.pipeline.yaml +26 -0
- package/examples/route-wiring-smoke-test/rejected/12-reject-loop-replay-unsafe.pipeline.yaml +55 -0
- package/examples/route-wiring-smoke-test/rejected/13-reject-multiple-loop-entries.pipeline.yaml +51 -0
- package/examples/route-wiring-smoke-test/rejected/14-reject-duplicate-stage-id.pipeline.yaml +35 -0
- package/examples/route-wiring-smoke-test/rejected/15-reject-unknown-route-target.pipeline.yaml +15 -0
- package/examples/route-wiring-smoke-test/rejected/16-reject-malformed-route-item.pipeline.yaml +15 -0
- package/examples/route-wiring-smoke-test/rejected/17-reject-io-incompatible.pipeline.yaml +33 -0
- package/examples/route-wiring-smoke-test/rejected/18-reject-nested-io.pipeline.yaml +51 -0
- package/examples/route-wiring-smoke-test/rejected/19-reject-array-item-io.pipeline.yaml +55 -0
- package/examples/route-wiring-smoke-test/rejected/20-reject-closed-io.pipeline.yaml +36 -0
- package/examples/route-wiring-smoke-test/rejected/21-reject-ref-io.pipeline.yaml +42 -0
- package/examples/route-wiring-smoke-test/rejected/22-reject-if-unknown-field.pipeline.yaml +33 -0
- package/examples/route-wiring-smoke-test/rejected/23-reject-if-optional-field.pipeline.yaml +32 -0
- package/examples/route-wiring-smoke-test/rejected/24-reject-if-empty-all.pipeline.yaml +31 -0
- package/examples/route-wiring-smoke-test/rejected/25-reject-if-gt-on-string.pipeline.yaml +33 -0
- package/examples/route-wiring-smoke-test/rejected/26-reject-if-optional-nested.pipeline.yaml +36 -0
- package/examples/route-wiring-smoke-test/rejected/27-reject-if-on-loop.pipeline.yaml +63 -0
- package/examples/route-wiring-smoke-test/rejected/29-reject-if-on-failed.pipeline.yaml +46 -0
- package/examples/route-wiring-smoke-test/smoke-test.task.yaml +4 -0
- package/examples/route-wiring-smoke-test/stages/branch-a.yaml +12 -0
- package/examples/route-wiring-smoke-test/stages/branch-b.yaml +12 -0
- package/examples/route-wiring-smoke-test/stages/decide.yaml +12 -0
- package/examples/route-wiring-smoke-test/stages/finish.yaml +12 -0
- package/examples/ship-feature/README.md +190 -0
- package/examples/ship-feature/feat-address-feedback.yaml +119 -0
- package/examples/ship-feature/feat-implement.yaml +180 -0
- package/examples/ship-feature/feat-plan.yaml +120 -0
- package/examples/ship-feature/feat-review.yaml +109 -0
- package/examples/ship-feature/feat-ship.yaml +203 -0
- package/examples/ship-feature/ship-feature.pipeline.yaml +44 -0
- package/examples/ship-feature/ship-feature.task.yaml +78 -0
- package/examples/stage-mcp/README.md +144 -0
- package/examples/stage-mcp/echo-mcp.mjs +20 -0
- package/examples/stage-mcp/stage-mcp-dead.pipeline.yaml +5 -0
- package/examples/stage-mcp/stage-mcp-dead.task.yaml +3 -0
- package/examples/stage-mcp/stage-mcp-missing-var.pipeline.yaml +5 -0
- package/examples/stage-mcp/stage-mcp-missing-var.task.yaml +3 -0
- package/examples/stage-mcp/stage-mcp.pipeline.yaml +5 -0
- package/examples/stage-mcp/stage-mcp.task.yaml +4 -0
- package/examples/stage-mcp/use-echo.yaml +20 -0
- package/examples/verify-tour/README.md +80 -0
- package/examples/verify-tour/verify-tour.pipeline.yaml +162 -0
- package/examples/verify-tour/verify-tour.task.yaml +11 -0
- package/package.json +6 -1
- package/skills/stageflow/SKILL.md +6 -6
- package/skills/stageflow/references/control-surface.md +11 -5
- package/skills/stageflow/scripts/detect-host.mjs +14 -1
- package/skills/stageflow/scripts/detect-host.test.mjs +29 -1
- package/skills/stageflow-author/SKILL.md +4 -3
- package/skills/stageflow-author/references/catalog-mapping.md +16 -0
- package/skills/stageflow-author/references/catalog-write-conventions.md +1 -1
- package/skills/stageflow-run/SKILL.md +20 -12
- package/skills/stageflow-run/references/mcp-call.md +9 -1
- package/skills/stageflow-run/references/task-and-pipeline-selection.md +16 -5
- package/skills/stageflow-run/scripts/mcp-call.mjs +46 -6
- package/skills/stageflow-run/scripts/mcp-call.test.mjs +64 -0
- package/skills/stageflow-session-capture/references/catalog-authoring.md +2 -0
- package/skills/stageflow-setup/SKILL.md +40 -8
- package/dist/ui/assets/index-Da5EHU6M.js +0 -119
package/dist/mcp/catalogTools.js
CHANGED
|
@@ -1,36 +1,49 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
1
|
import { z } from "zod";
|
|
3
|
-
import {
|
|
2
|
+
import { catalogPathErrorBody, CatalogPathError, resolveCatalogRelativePath, resolveCatalogStartInput, selectCatalogRootForStart, } from "../config/catalogRelativePath.js";
|
|
3
|
+
import { listModelsMultiProject, listPipelinesMultiProject, listTasksMultiProject, } from "../config/multiProjectCatalog.js";
|
|
4
|
+
import { resolveCatalogRoots } from "../config/resolveCatalogRoots.js";
|
|
4
5
|
import { describePipeline } from "../config/describePipeline.js";
|
|
5
6
|
import { loadPipeline } from "../config/loadPipeline.js";
|
|
7
|
+
import { readYamlObject } from "../config/readYamlObject.js";
|
|
6
8
|
import { validateCatalog } from "../config/validateCatalog.js";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
+
import { writeAudit } from "../logging/audit.js";
|
|
10
|
+
import { logger as rootLogger } from "../logging/logger.js";
|
|
11
|
+
import { PACKAGE_VERSION, BUILD_SHA } from "../package-meta.js";
|
|
9
12
|
import { PipelineValidationError } from "../runtime/pipelineValidationError.js";
|
|
13
|
+
import { PipelinePreflightError } from "../runtime/pipelineRunner.js";
|
|
14
|
+
import { EnvelopeRefError, resolveEnvelopeRefsToTask, } from "../runtime/resolveEnvelopeRef.js";
|
|
15
|
+
import { isTerminalProjection, isWaitingProjection, waitRun } from "./waitRun.js";
|
|
10
16
|
import { mapStoreLookupError } from "../server/operatorResults.js";
|
|
17
|
+
import { callerIdFromRequestAuth, getRequestAuth, } from "../server/requestAuthContext.js";
|
|
11
18
|
import { projectRunForMcp } from "./projectRun.js";
|
|
12
19
|
import { classifyArtifactContent, readRunArtifactBytes } from "./readArtifact.js";
|
|
13
20
|
import { imageResult, textResult } from "./toolResults.js";
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
21
|
+
import { buildRunExportPayload } from "../runstore/exportRunPayload.js";
|
|
22
|
+
import { redactRunManifestForRead } from "../runstore/runManifest.js";
|
|
23
|
+
import { getAgentDir } from "@earendil-works/pi-coding-agent";
|
|
24
|
+
import { runSkillsDir } from "../runtime/runSkills.js";
|
|
25
|
+
import { listSkillsWithOrigin } from "../config/listSkills.js";
|
|
26
|
+
import { findTokenShapedField, pickCheckoutOverride, tokenRejectedPayload, } from "../runtime/startPayload.js";
|
|
27
|
+
import { loadPipelineFromObjectOutcome, loadPipelineOutcome, } from "../config/loadPipeline.js";
|
|
28
|
+
import { preflightFailureCode, runPipelinePreflight, } from "../preflight/pipelinePreflight.js";
|
|
29
|
+
import { toolchainHealthMap } from "../preflight/toolchain.js";
|
|
30
|
+
const auditLog = rootLogger.child({ component: "audit" });
|
|
31
|
+
const gitIdentitySchema = z
|
|
32
|
+
.object({
|
|
33
|
+
name: z.string().optional(),
|
|
34
|
+
email: z.string().optional(),
|
|
35
|
+
})
|
|
36
|
+
.strict();
|
|
28
37
|
const taskFileSchema = z.object({
|
|
29
38
|
id: z.string(),
|
|
30
39
|
goal: z.string(),
|
|
31
40
|
context: z.string().optional(),
|
|
32
41
|
constraints: z.string().optional(),
|
|
33
42
|
checkout: z.string().optional(),
|
|
43
|
+
repository: z.string().optional(),
|
|
44
|
+
ref: z.string().optional(),
|
|
45
|
+
run_branch_template: z.string().optional(),
|
|
46
|
+
git_identity: gitIdentitySchema.optional(),
|
|
34
47
|
input: z.record(z.string(), z.unknown()).optional(),
|
|
35
48
|
});
|
|
36
49
|
/**
|
|
@@ -47,75 +60,207 @@ const inlinePipelineSchema = z
|
|
|
47
60
|
agent: z.unknown().optional(),
|
|
48
61
|
model: z.unknown().optional(),
|
|
49
62
|
schemas: z.unknown().optional(),
|
|
63
|
+
requires: z.unknown().optional(),
|
|
50
64
|
})
|
|
51
65
|
.strict();
|
|
52
66
|
const startRunSchema = z
|
|
53
67
|
.object({
|
|
54
68
|
pipeline: z
|
|
55
69
|
.union([z.string(), inlinePipelineSchema])
|
|
56
|
-
.describe("
|
|
70
|
+
.describe("Catalog-relative pipeline path, or an inline pipeline definition object ({ id, stages: [...] }) authored directly in this call"),
|
|
57
71
|
task_path: z.string().optional(),
|
|
58
72
|
task: taskFileSchema.optional(),
|
|
73
|
+
project_root: z.string().optional(),
|
|
74
|
+
checkout: z
|
|
75
|
+
.string()
|
|
76
|
+
.optional()
|
|
77
|
+
.describe("Catalog-relative checkout path (maps to RunManager checkoutOverride); absolute paths are rejected with absolute_path_not_allowed"),
|
|
78
|
+
checkout_override: z
|
|
79
|
+
.string()
|
|
80
|
+
.optional()
|
|
81
|
+
.describe("Alias of checkout; prefer checkout"),
|
|
82
|
+
skip_gates: z.boolean().optional(),
|
|
83
|
+
git_sha: z.string().optional(),
|
|
84
|
+
ci_pr_url: z.string().optional(),
|
|
85
|
+
ci_job_url: z.string().optional(),
|
|
86
|
+
skills: z
|
|
87
|
+
.record(z.string(), z.record(z.string(), z.string()))
|
|
88
|
+
.optional()
|
|
89
|
+
.describe("Run-scoped skills: name → { relativePath: utf-8 contents }. Requires SKILL.md per name; materialised under the run workspace skills dir (never the worktree)"),
|
|
59
90
|
})
|
|
91
|
+
.passthrough()
|
|
60
92
|
.refine((data) => Boolean(data.task_path) !== Boolean(data.task), {
|
|
61
93
|
message: "Exactly one of task_path or task is required",
|
|
62
94
|
});
|
|
63
|
-
|
|
95
|
+
/**
|
|
96
|
+
* Deliberately thin, same reasoning as inlinePipelineSchema above: real
|
|
97
|
+
* structural validation of the stage body happens downstream through the
|
|
98
|
+
* same stage loader a pipeline's inline stage goes through.
|
|
99
|
+
*/
|
|
100
|
+
const envelopeRefSchema = z.object({
|
|
101
|
+
runId: z.string(),
|
|
102
|
+
stageId: z.string(),
|
|
103
|
+
attempt: z.number().int().positive().optional(),
|
|
104
|
+
});
|
|
105
|
+
const runStageSchema = z
|
|
106
|
+
.object({
|
|
107
|
+
stage: z
|
|
108
|
+
.union([z.string(), z.record(z.string(), z.unknown())])
|
|
109
|
+
.describe("Catalog-relative path to a stage YAML file (same path contract as start_run — absolute paths rejected, must be inside a registered project_root), or a bare inline stage body object ({ id, system_prompt, io, model?, gate_kinds?, mcp?, verify?, timeout_ms? } — no uses:/route/pipeline wrapper) authored directly in this call"),
|
|
110
|
+
project_root: z
|
|
111
|
+
.string()
|
|
112
|
+
.optional()
|
|
113
|
+
.describe("Catalog project root to resolve a string stage path against; required when multiple catalog roots are configured and no sole non-seeded root exists"),
|
|
114
|
+
task_path: z.string().optional(),
|
|
115
|
+
task: taskFileSchema.optional(),
|
|
116
|
+
envelope_ref: z
|
|
117
|
+
.union([envelopeRefSchema, z.array(envelopeRefSchema).min(1)])
|
|
118
|
+
.optional()
|
|
119
|
+
.describe("Resolve one or more previously stored StageEnvelopes (from another run_stage call or from any stage inside a full pipeline run) and use them as this stage's input, instead of an inline task/task_path. A single ref: its payload becomes input, its summary becomes goal. Multiple refs (an array): each resolved payload is namespaced under its stageId in input (disambiguated by runId on a stageId collision), and summaries are combined into goal."),
|
|
120
|
+
checkout: z
|
|
121
|
+
.string()
|
|
122
|
+
.optional()
|
|
123
|
+
.describe("Optional checkout to use with envelope_ref (ignored with task/task_path, which carry their own checkout). Resolving envelope_ref never implies a checkout on its own."),
|
|
124
|
+
model: z
|
|
125
|
+
.string()
|
|
126
|
+
.optional()
|
|
127
|
+
.describe("Override the model/backend for this call only, taking precedence over the stage's own declared model and the global default. Omit to use the stage's own model (or the global default)."),
|
|
128
|
+
blocking: z
|
|
129
|
+
.boolean()
|
|
130
|
+
.optional()
|
|
131
|
+
.describe("When true, wait for the run to reach a terminal or waiting state and return the result in this same call, instead of returning immediately with just { runId }"),
|
|
132
|
+
timeout_ms: z
|
|
133
|
+
.number()
|
|
134
|
+
.optional()
|
|
135
|
+
.describe("Wait budget in ms when blocking is true (same bounds as wait_run)"),
|
|
136
|
+
})
|
|
137
|
+
.refine((data) => [data.task_path, data.task, data.envelope_ref].filter(Boolean).length === 1, { message: "Exactly one of task_path, task, or envelope_ref is required" });
|
|
138
|
+
const runStatusSchema = z.enum([
|
|
139
|
+
"created",
|
|
140
|
+
"queued",
|
|
141
|
+
"running",
|
|
142
|
+
"succeeded",
|
|
143
|
+
"failed",
|
|
144
|
+
"cancelled",
|
|
145
|
+
]);
|
|
64
146
|
export function registerCatalogTools(server, deps) {
|
|
65
147
|
const { manager, store, cwd } = deps;
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
148
|
+
const agentDir = deps.agentDir ?? getAgentDir();
|
|
149
|
+
server.registerTool("list_skills", {
|
|
150
|
+
description: "List skills with name, description, and origin (run|checkout|host). Optional runId scopes to that run's resolution view (run-tier skills first, then checkout .pi/skills, then host).",
|
|
151
|
+
inputSchema: z.object({
|
|
152
|
+
runId: z.string().optional(),
|
|
153
|
+
}),
|
|
154
|
+
}, async ({ runId }) => {
|
|
155
|
+
try {
|
|
156
|
+
let runSkills;
|
|
157
|
+
let checkoutRoot;
|
|
158
|
+
if (runId !== undefined) {
|
|
159
|
+
const meta = await store.readRunMeta(runId);
|
|
160
|
+
runSkills = runSkillsDir(store.getWorkspaceDir(runId));
|
|
161
|
+
checkoutRoot = meta.checkout_root;
|
|
78
162
|
}
|
|
79
|
-
|
|
80
|
-
|
|
163
|
+
const catalog = await listSkillsWithOrigin({
|
|
164
|
+
cwd,
|
|
165
|
+
agentDir,
|
|
166
|
+
...(runSkills !== undefined ? { runSkillsDir: runSkills } : {}),
|
|
167
|
+
...(checkoutRoot !== undefined ? { checkoutRoot } : {}),
|
|
168
|
+
});
|
|
169
|
+
return textResult({
|
|
170
|
+
skills: catalog.skills,
|
|
171
|
+
diagnostics: catalog.diagnostics,
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
catch (err) {
|
|
175
|
+
if (runId !== undefined) {
|
|
176
|
+
const mapped = mapStoreLookupError(err, { policy: "run" });
|
|
177
|
+
return textResult({ error: mapped.error, status: mapped.status }, true);
|
|
81
178
|
}
|
|
179
|
+
throw err;
|
|
82
180
|
}
|
|
83
|
-
|
|
181
|
+
});
|
|
182
|
+
server.registerTool("list_pipelines", {
|
|
183
|
+
description: "List manifest-declared pipeline paths across every project this host knows about (registered store roots and seeded roots). Each entry is tagged with project_root. Optional project_root filter narrows; unknown value returns unknown_project_root.",
|
|
184
|
+
inputSchema: z.object({
|
|
185
|
+
project_root: z.string().optional(),
|
|
186
|
+
}),
|
|
187
|
+
}, async ({ project_root }) => {
|
|
188
|
+
const result = await listPipelinesMultiProject({
|
|
189
|
+
store,
|
|
190
|
+
bootCwd: cwd,
|
|
191
|
+
projectRootFilter: project_root,
|
|
192
|
+
});
|
|
193
|
+
if (result.root_errors.some((e) => e.code === "unknown_project_root") &&
|
|
194
|
+
result.items.length === 0) {
|
|
195
|
+
return textResult({
|
|
196
|
+
error: result.root_errors[0].message,
|
|
197
|
+
code: "unknown_project_root",
|
|
198
|
+
root_errors: result.root_errors,
|
|
199
|
+
}, true);
|
|
200
|
+
}
|
|
201
|
+
return textResult({
|
|
202
|
+
pipelines: result.items,
|
|
203
|
+
root_errors: result.root_errors,
|
|
204
|
+
});
|
|
84
205
|
});
|
|
85
206
|
server.registerTool("list_tasks", {
|
|
86
|
-
description: "List manifest-declared task paths across every project this host knows about (
|
|
87
|
-
inputSchema: z.object({
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
207
|
+
description: "List manifest-declared task paths across every project this host knows about (registered store roots and seeded roots). Each entry is tagged with project_root. Optional project_root filter narrows; unknown value returns unknown_project_root.",
|
|
208
|
+
inputSchema: z.object({
|
|
209
|
+
project_root: z.string().optional(),
|
|
210
|
+
}),
|
|
211
|
+
}, async ({ project_root }) => {
|
|
212
|
+
const result = await listTasksMultiProject({
|
|
213
|
+
store,
|
|
214
|
+
bootCwd: cwd,
|
|
215
|
+
projectRootFilter: project_root,
|
|
216
|
+
});
|
|
217
|
+
if (result.root_errors.some((e) => e.code === "unknown_project_root") &&
|
|
218
|
+
result.items.length === 0) {
|
|
219
|
+
return textResult({
|
|
220
|
+
error: result.root_errors[0].message,
|
|
221
|
+
code: "unknown_project_root",
|
|
222
|
+
root_errors: result.root_errors,
|
|
223
|
+
}, true);
|
|
101
224
|
}
|
|
102
|
-
return textResult({
|
|
225
|
+
return textResult({
|
|
226
|
+
tasks: result.items,
|
|
227
|
+
root_errors: result.root_errors,
|
|
228
|
+
});
|
|
103
229
|
});
|
|
104
230
|
server.registerTool("list_models", {
|
|
105
|
-
description: "List catalog model ids
|
|
106
|
-
inputSchema: z.object({
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
231
|
+
description: "List catalog model ids across every project this host knows about (same multi-root source as GET /api/models). Optional project_root filter narrows.",
|
|
232
|
+
inputSchema: z.object({
|
|
233
|
+
project_root: z.string().optional(),
|
|
234
|
+
}),
|
|
235
|
+
}, async ({ project_root }) => {
|
|
236
|
+
const result = await listModelsMultiProject({
|
|
237
|
+
store,
|
|
238
|
+
bootCwd: cwd,
|
|
239
|
+
projectRootFilter: project_root,
|
|
240
|
+
});
|
|
241
|
+
if (result.root_errors.some((e) => e.code === "unknown_project_root") &&
|
|
242
|
+
result.items.length === 0) {
|
|
243
|
+
return textResult({
|
|
244
|
+
error: result.root_errors[0].message,
|
|
245
|
+
code: "unknown_project_root",
|
|
246
|
+
root_errors: result.root_errors,
|
|
247
|
+
}, true);
|
|
248
|
+
}
|
|
249
|
+
return textResult({
|
|
250
|
+
models: result.models,
|
|
251
|
+
entries: result.items,
|
|
252
|
+
root_errors: result.root_errors,
|
|
253
|
+
});
|
|
110
254
|
});
|
|
111
255
|
server.registerTool("list_runs", {
|
|
112
|
-
description: "List known pipeline runs. Optional filters: status, since (ISO created_at lower bound), pipeline (id or path).",
|
|
256
|
+
description: "List known pipeline runs. Optional filters: status, since (ISO created_at lower bound), pipeline (id or path), caller_id.",
|
|
113
257
|
inputSchema: z.object({
|
|
114
258
|
status: runStatusSchema.optional(),
|
|
115
259
|
since: z.string().optional(),
|
|
116
260
|
pipeline: z.string().optional(),
|
|
261
|
+
caller_id: z.string().optional(),
|
|
117
262
|
}),
|
|
118
|
-
}, async ({ status, since, pipeline }) => {
|
|
263
|
+
}, async ({ status, since, pipeline, caller_id }) => {
|
|
119
264
|
const filter = {};
|
|
120
265
|
if (status !== undefined)
|
|
121
266
|
filter.status = status;
|
|
@@ -127,17 +272,106 @@ export function registerCatalogTools(server, deps) {
|
|
|
127
272
|
}
|
|
128
273
|
if (pipeline !== undefined)
|
|
129
274
|
filter.pipeline = pipeline;
|
|
275
|
+
if (caller_id !== undefined)
|
|
276
|
+
filter.caller_id = caller_id;
|
|
130
277
|
const runs = await store.listRuns(Object.keys(filter).length > 0 ? filter : undefined);
|
|
131
278
|
return textResult({ runs });
|
|
132
279
|
});
|
|
133
280
|
server.registerTool("get_health", {
|
|
134
|
-
description: "Server health and soft-max run capacity: activeRunIds, activeCount, maxConcurrent, slotsAvailable, version. Start until slotsAvailable is 0; then wait for a run to finish or raise STAGEFLOW_MAX_CONCURRENT_RUNS.",
|
|
281
|
+
description: "Server health and soft-max run capacity: activeRunIds, activeCount, maxConcurrent, slotsAvailable, activeStageProcesses, version, plus disk breakdown (disk.runs_bytes, worktrees_bytes, repos_bytes, state_db_bytes, a2a_artifacts_bytes, free_bytes) for the durable root. Start until slotsAvailable is 0; then wait for a run to finish or raise STAGEFLOW_MAX_CONCURRENT_RUNS.",
|
|
135
282
|
inputSchema: z.object({}),
|
|
136
|
-
}, async () => textResult({
|
|
283
|
+
}, async () => textResult({
|
|
284
|
+
...(await manager.getHealthWithDisk()),
|
|
285
|
+
version: PACKAGE_VERSION,
|
|
286
|
+
build_sha: BUILD_SHA,
|
|
287
|
+
toolchain: toolchainHealthMap(),
|
|
288
|
+
}));
|
|
289
|
+
server.registerTool("preflight", {
|
|
290
|
+
description: "Check pipeline requires:/secrets:/mcp against the Host toolchain manifest and curated stage env before start_run. Accepts pipeline path or inline definition (same union as start_run). Returns { ok, checks } with status ok|missing_tool|tool_version_mismatch|unknown_version|secret_unavailable|unresolved_var. Does not create a Run. unknown_version is ok unless strict:true.",
|
|
291
|
+
inputSchema: z.object({
|
|
292
|
+
pipeline: z
|
|
293
|
+
.union([z.string(), inlinePipelineSchema])
|
|
294
|
+
.describe("Catalog-relative pipeline path, or an inline pipeline definition object"),
|
|
295
|
+
project_root: z.string().optional(),
|
|
296
|
+
strict: z
|
|
297
|
+
.boolean()
|
|
298
|
+
.optional()
|
|
299
|
+
.describe("When true, unknown_version fails (default false)"),
|
|
300
|
+
}),
|
|
301
|
+
}, async ({ pipeline, project_root, strict }) => {
|
|
302
|
+
const roots = await resolveCatalogRoots({
|
|
303
|
+
store: deps.store,
|
|
304
|
+
bootCwd: deps.cwd,
|
|
305
|
+
});
|
|
306
|
+
let loaded;
|
|
307
|
+
let projectRoot;
|
|
308
|
+
try {
|
|
309
|
+
const wireRoot = selectCatalogRootForStart(roots, project_root);
|
|
310
|
+
projectRoot = wireRoot.project_root;
|
|
311
|
+
if (typeof pipeline === "string") {
|
|
312
|
+
const resolved = resolveCatalogRelativePath({
|
|
313
|
+
inputPath: pipeline,
|
|
314
|
+
projectRoot: project_root,
|
|
315
|
+
roots,
|
|
316
|
+
fieldName: "pipeline",
|
|
317
|
+
});
|
|
318
|
+
projectRoot = resolved.root.project_root;
|
|
319
|
+
const outcome = await loadPipelineOutcome(resolved.absolutePath, {
|
|
320
|
+
cwd: deps.cwd,
|
|
321
|
+
projectRoot,
|
|
322
|
+
});
|
|
323
|
+
if (!outcome.ok) {
|
|
324
|
+
return textResult({
|
|
325
|
+
ok: false,
|
|
326
|
+
error: outcome.issues[0]?.message ?? "pipeline load failed",
|
|
327
|
+
code: outcome.issues[0]?.code ?? "config_invalid",
|
|
328
|
+
issues: outcome.issues,
|
|
329
|
+
}, true);
|
|
330
|
+
}
|
|
331
|
+
loaded = outcome.value;
|
|
332
|
+
}
|
|
333
|
+
else {
|
|
334
|
+
const outcome = await loadPipelineFromObjectOutcome(pipeline, {
|
|
335
|
+
cwd: deps.cwd,
|
|
336
|
+
projectRoot,
|
|
337
|
+
});
|
|
338
|
+
if (!outcome.ok) {
|
|
339
|
+
return textResult({
|
|
340
|
+
ok: false,
|
|
341
|
+
error: outcome.issues[0]?.message ?? "pipeline load failed",
|
|
342
|
+
code: outcome.issues[0]?.code ?? "config_invalid",
|
|
343
|
+
issues: outcome.issues,
|
|
344
|
+
}, true);
|
|
345
|
+
}
|
|
346
|
+
loaded = outcome.value;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
catch (err) {
|
|
350
|
+
if (err instanceof CatalogPathError) {
|
|
351
|
+
return textResult(catalogPathErrorBody(err), true);
|
|
352
|
+
}
|
|
353
|
+
throw err;
|
|
354
|
+
}
|
|
355
|
+
const result = await runPipelinePreflight(loaded, {
|
|
356
|
+
projectRoot,
|
|
357
|
+
strict: strict === true,
|
|
358
|
+
});
|
|
359
|
+
const code = preflightFailureCode(result, { strict: strict === true });
|
|
360
|
+
return textResult({
|
|
361
|
+
ok: result.ok,
|
|
362
|
+
checks: result.checks,
|
|
363
|
+
...(code !== undefined ? { code } : {}),
|
|
364
|
+
});
|
|
365
|
+
});
|
|
137
366
|
server.registerTool("start_run", {
|
|
138
|
-
description: "Start a pipeline run
|
|
367
|
+
description: "Start a pipeline run. Accepted params: pipeline (catalog-relative path or inline { id, stages: [...] } — stages are YAML stage bodies, no uses: refs), task_path XOR task (inline task may include repository/ref or checkout; repository XOR checkout with code task.binding_conflict), project_root, checkout (catalog-relative; prefer this name; absolute → absolute_path_not_allowed), checkout_override (alias of checkout), skip_gates, git_sha, ci_pr_url, ci_job_url, skills (name → { relativePath: utf-8 contents }; requires SKILL.md; materialised under runs/<runId>/skills/, never the worktree). REST POST /api/runs accepts path pipelines only (no inline pipeline). Returns { runId } or { runId, queued: true, queuePosition }. Errors: busy_capacity, busy_checkout, insufficient_disk, start.token_rejected, skills_*, inline_pipeline_too_large, catalog path-contract codes.",
|
|
139
368
|
inputSchema: startRunSchema,
|
|
140
|
-
}, async (
|
|
369
|
+
}, async (args) => {
|
|
370
|
+
const tokenField = findTokenShapedField(args);
|
|
371
|
+
if (tokenField !== undefined) {
|
|
372
|
+
return textResult(tokenRejectedPayload(tokenField), true);
|
|
373
|
+
}
|
|
374
|
+
const { pipeline, task_path, task, project_root, checkout, checkout_override, skip_gates, git_sha, ci_pr_url, ci_job_url, skills, } = args;
|
|
141
375
|
if (typeof pipeline === "string" && !pipeline.trim()) {
|
|
142
376
|
return textResult({ error: "pipeline is required" }, true);
|
|
143
377
|
}
|
|
@@ -145,21 +379,243 @@ export function registerCatalogTools(server, deps) {
|
|
|
145
379
|
if (taskInput === undefined) {
|
|
146
380
|
return textResult({ error: "Exactly one of task_path or task is required" }, true);
|
|
147
381
|
}
|
|
382
|
+
let wireRoot;
|
|
383
|
+
let roots;
|
|
384
|
+
try {
|
|
385
|
+
({ wireRoot, roots } = await resolveCatalogStartInput({ store: deps.store, bootCwd: deps.cwd }, project_root));
|
|
386
|
+
}
|
|
387
|
+
catch (err) {
|
|
388
|
+
if (err instanceof CatalogPathError) {
|
|
389
|
+
return textResult(catalogPathErrorBody(err), true);
|
|
390
|
+
}
|
|
391
|
+
throw err;
|
|
392
|
+
}
|
|
393
|
+
const wireProjectRoot = wireRoot.project_root;
|
|
394
|
+
let resolvedPipeline = pipeline;
|
|
395
|
+
let resolvedTask = taskInput;
|
|
396
|
+
let resolvedCheckout;
|
|
397
|
+
try {
|
|
398
|
+
if (typeof pipeline === "string") {
|
|
399
|
+
resolvedPipeline = resolveCatalogRelativePath({
|
|
400
|
+
inputPath: pipeline,
|
|
401
|
+
projectRoot: wireProjectRoot,
|
|
402
|
+
roots,
|
|
403
|
+
fieldName: "pipeline",
|
|
404
|
+
}).absolutePath;
|
|
405
|
+
}
|
|
406
|
+
if (typeof task_path === "string") {
|
|
407
|
+
resolvedTask = resolveCatalogRelativePath({
|
|
408
|
+
inputPath: task_path,
|
|
409
|
+
projectRoot: wireProjectRoot,
|
|
410
|
+
roots,
|
|
411
|
+
fieldName: "task_path",
|
|
412
|
+
}).absolutePath;
|
|
413
|
+
}
|
|
414
|
+
const rawCheckout = pickCheckoutOverride({ checkout, checkout_override });
|
|
415
|
+
if (rawCheckout !== undefined) {
|
|
416
|
+
resolvedCheckout = resolveCatalogRelativePath({
|
|
417
|
+
inputPath: rawCheckout,
|
|
418
|
+
projectRoot: wireProjectRoot,
|
|
419
|
+
roots,
|
|
420
|
+
fieldName: "checkout",
|
|
421
|
+
}).absolutePath;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
catch (err) {
|
|
425
|
+
if (err instanceof CatalogPathError) {
|
|
426
|
+
return textResult(catalogPathErrorBody(err), true);
|
|
427
|
+
}
|
|
428
|
+
throw err;
|
|
429
|
+
}
|
|
430
|
+
const callerId = callerIdFromRequestAuth();
|
|
148
431
|
let result;
|
|
149
432
|
try {
|
|
150
|
-
result = await manager.startRun({
|
|
433
|
+
result = await manager.startRun({
|
|
434
|
+
pipeline: resolvedPipeline,
|
|
435
|
+
task: resolvedTask,
|
|
436
|
+
projectRoot: wireRoot.path,
|
|
437
|
+
...(resolvedCheckout !== undefined
|
|
438
|
+
? { checkoutOverride: resolvedCheckout }
|
|
439
|
+
: {}),
|
|
440
|
+
...(skip_gates !== undefined ? { skipGates: skip_gates } : {}),
|
|
441
|
+
...(git_sha !== undefined ? { gitSha: git_sha } : {}),
|
|
442
|
+
...(ci_pr_url !== undefined ? { ciPrUrl: ci_pr_url } : {}),
|
|
443
|
+
...(ci_job_url !== undefined ? { ciJobUrl: ci_job_url } : {}),
|
|
444
|
+
...(skills !== undefined ? { skills } : {}),
|
|
445
|
+
callerId,
|
|
446
|
+
});
|
|
151
447
|
}
|
|
152
448
|
catch (err) {
|
|
153
449
|
if (err instanceof PipelineValidationError) {
|
|
450
|
+
writeAudit(auditLog, {
|
|
451
|
+
caller_id: callerId,
|
|
452
|
+
surface: getRequestAuth()?.surface ?? "mcp",
|
|
453
|
+
action: "start_run",
|
|
454
|
+
outcome: "error",
|
|
455
|
+
error_code: "pipeline_validation",
|
|
456
|
+
});
|
|
154
457
|
return textResult({ error: "Pipeline validation failed", validation: err.result }, true);
|
|
155
458
|
}
|
|
459
|
+
if (err instanceof PipelinePreflightError) {
|
|
460
|
+
writeAudit(auditLog, {
|
|
461
|
+
caller_id: callerId,
|
|
462
|
+
surface: getRequestAuth()?.surface ?? "mcp",
|
|
463
|
+
action: "start_run",
|
|
464
|
+
outcome: "error",
|
|
465
|
+
error_code: err.code,
|
|
466
|
+
});
|
|
467
|
+
return textResult(err.toNetworkBody(), true);
|
|
468
|
+
}
|
|
156
469
|
throw err;
|
|
157
470
|
}
|
|
158
471
|
if (!result.ok) {
|
|
472
|
+
writeAudit(auditLog, {
|
|
473
|
+
caller_id: callerId,
|
|
474
|
+
surface: getRequestAuth()?.surface ?? "mcp",
|
|
475
|
+
action: "start_run",
|
|
476
|
+
outcome: "error",
|
|
477
|
+
error_code: result.code,
|
|
478
|
+
});
|
|
159
479
|
const { ok: _ok, reason, ...rest } = result;
|
|
160
480
|
return textResult({ error: reason, ...rest }, true);
|
|
161
481
|
}
|
|
162
|
-
|
|
482
|
+
writeAudit(auditLog, {
|
|
483
|
+
caller_id: callerId,
|
|
484
|
+
surface: getRequestAuth()?.surface ?? "mcp",
|
|
485
|
+
action: "start_run",
|
|
486
|
+
target_run_id: result.runId,
|
|
487
|
+
outcome: "ok",
|
|
488
|
+
});
|
|
489
|
+
return textResult({
|
|
490
|
+
runId: result.runId,
|
|
491
|
+
...(result.queued === true
|
|
492
|
+
? {
|
|
493
|
+
queued: true,
|
|
494
|
+
queuePosition: result.queuePosition,
|
|
495
|
+
...(result.queuedCode !== undefined
|
|
496
|
+
? { queuedCode: result.queuedCode }
|
|
497
|
+
: {}),
|
|
498
|
+
}
|
|
499
|
+
: {}),
|
|
500
|
+
});
|
|
501
|
+
});
|
|
502
|
+
server.registerTool("run_stage", {
|
|
503
|
+
description: "Run a single stage directly, without authoring a pipeline. `stage` is a filesystem path to a stage YAML file, or a bare inline stage body ({ id, system_prompt, io, model?, gate_kinds?, mcp?, verify?, timeout_ms? } — no uses:/route/pipeline wrapper), and exactly one of task_path, an inline task, or envelope_ref ({ runId, stageId, attempt? }) to resolve a previously stored envelope — from another run_stage call or any stage in a full pipeline run — as this stage's input. Internally this synthesizes a one-stage pipeline and executes it through the normal run path, so it shows up in list_runs/get_run and is polled with wait_run / get_envelope exactly like any other run. By default returns { runId, stageId } immediately (async); pass blocking:true to wait in this same call and get back { runId, stageId, status: \"completed\"|\"needs_input\"|\"timeout\", envelope? , pending_prompt? }.",
|
|
504
|
+
inputSchema: runStageSchema,
|
|
505
|
+
}, async ({ stage, project_root, task_path, task, envelope_ref, checkout, model, blocking, timeout_ms }) => {
|
|
506
|
+
let taskInput = task_path ?? task;
|
|
507
|
+
if (envelope_ref) {
|
|
508
|
+
try {
|
|
509
|
+
taskInput = await resolveEnvelopeRefsToTask(store, envelope_ref, checkout);
|
|
510
|
+
}
|
|
511
|
+
catch (err) {
|
|
512
|
+
if (err instanceof EnvelopeRefError) {
|
|
513
|
+
return textResult({ error: err.message, status: err.status }, true);
|
|
514
|
+
}
|
|
515
|
+
throw err;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
if (taskInput === undefined) {
|
|
519
|
+
return textResult({ error: "Exactly one of task_path, task, or envelope_ref is required" }, true);
|
|
520
|
+
}
|
|
521
|
+
let stageBody;
|
|
522
|
+
let stageProjectRoot;
|
|
523
|
+
if (typeof stage === "string") {
|
|
524
|
+
if (!stage.trim()) {
|
|
525
|
+
return textResult({ error: "stage is required" }, true);
|
|
526
|
+
}
|
|
527
|
+
let absPath = "";
|
|
528
|
+
try {
|
|
529
|
+
const { wireRoot, roots } = await resolveCatalogStartInput({ store: deps.store, bootCwd: deps.cwd }, project_root);
|
|
530
|
+
stageProjectRoot = wireRoot.path;
|
|
531
|
+
absPath = resolveCatalogRelativePath({
|
|
532
|
+
inputPath: stage,
|
|
533
|
+
projectRoot: wireRoot.project_root,
|
|
534
|
+
roots,
|
|
535
|
+
fieldName: "stage",
|
|
536
|
+
}).absolutePath;
|
|
537
|
+
}
|
|
538
|
+
catch (err) {
|
|
539
|
+
if (err instanceof CatalogPathError) {
|
|
540
|
+
return textResult(catalogPathErrorBody(err), true);
|
|
541
|
+
}
|
|
542
|
+
throw err;
|
|
543
|
+
}
|
|
544
|
+
try {
|
|
545
|
+
stageBody = await readYamlObject(absPath);
|
|
546
|
+
}
|
|
547
|
+
catch (err) {
|
|
548
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
549
|
+
return textResult({ error: `Failed to read stage file: ${message}` }, true);
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
else {
|
|
553
|
+
stageBody = stage;
|
|
554
|
+
}
|
|
555
|
+
if (typeof stageBody.id !== "string" || !stageBody.id.trim()) {
|
|
556
|
+
return textResult({ error: "stage.id is required" }, true);
|
|
557
|
+
}
|
|
558
|
+
const stageId = stageBody.id;
|
|
559
|
+
// A call-level model override wins over both the stage's own declared
|
|
560
|
+
// model and the global default: it replaces the field the stage body
|
|
561
|
+
// itself would otherwise resolve through, rather than adding a new
|
|
562
|
+
// tier to resolveModel's stage > pipeline > global chain.
|
|
563
|
+
const effectiveStageBody = model !== undefined ? { ...stageBody, model } : stageBody;
|
|
564
|
+
const pipeline = {
|
|
565
|
+
id: `standalone-${stageId}`,
|
|
566
|
+
stages: [effectiveStageBody],
|
|
567
|
+
};
|
|
568
|
+
let result;
|
|
569
|
+
try {
|
|
570
|
+
result = await manager.startRun({
|
|
571
|
+
pipeline,
|
|
572
|
+
task: taskInput,
|
|
573
|
+
...(stageProjectRoot !== undefined ? { projectRoot: stageProjectRoot } : {}),
|
|
574
|
+
});
|
|
575
|
+
}
|
|
576
|
+
catch (err) {
|
|
577
|
+
if (err instanceof PipelineValidationError) {
|
|
578
|
+
return textResult({ error: "Stage validation failed", validation: err.result }, true);
|
|
579
|
+
}
|
|
580
|
+
throw err;
|
|
581
|
+
}
|
|
582
|
+
if (!result.ok) {
|
|
583
|
+
const { ok: _ok, reason, ...rest } = result;
|
|
584
|
+
return textResult({ error: reason, ...rest }, true);
|
|
585
|
+
}
|
|
586
|
+
const runId = result.runId;
|
|
587
|
+
if (!blocking) {
|
|
588
|
+
return textResult({ runId, stageId });
|
|
589
|
+
}
|
|
590
|
+
const waited = await waitRun({ store, runId, timeoutMs: timeout_ms, until: "any" });
|
|
591
|
+
if (!waited.ok) {
|
|
592
|
+
return textResult({
|
|
593
|
+
error: waited.error,
|
|
594
|
+
...(waited.status !== undefined ? { status: waited.status } : {}),
|
|
595
|
+
...(waited.code !== undefined ? { code: waited.code } : {}),
|
|
596
|
+
}, true);
|
|
597
|
+
}
|
|
598
|
+
const stageProjection = waited.run.stages.find((s) => s.stage_id === stageId);
|
|
599
|
+
if (isTerminalProjection(waited.run)) {
|
|
600
|
+
return textResult({
|
|
601
|
+
runId,
|
|
602
|
+
stageId,
|
|
603
|
+
status: "completed",
|
|
604
|
+
envelope: stageProjection?.envelope ?? null,
|
|
605
|
+
});
|
|
606
|
+
}
|
|
607
|
+
if (isWaitingProjection(waited.run)) {
|
|
608
|
+
return textResult({
|
|
609
|
+
runId,
|
|
610
|
+
stageId,
|
|
611
|
+
status: "needs_input",
|
|
612
|
+
pending_prompt: stageProjection?.pending_prompt,
|
|
613
|
+
waiting_kind: waited.run.waiting_kind,
|
|
614
|
+
waiting_prompt_id: waited.run.waiting_prompt_id,
|
|
615
|
+
waiting_summary: waited.run.waiting_summary,
|
|
616
|
+
});
|
|
617
|
+
}
|
|
618
|
+
return textResult({ runId, stageId, status: "timeout" });
|
|
163
619
|
});
|
|
164
620
|
server.registerTool("get_run", {
|
|
165
621
|
description: "Poll a run: status, stage statuses, waiting_* / pending_prompt HITL fields, and envelope summary/payload/artifact paths (no events). Use list_stage_events, get_envelope, or get_stage_verification for stage detail.",
|
|
@@ -169,7 +625,25 @@ export function registerCatalogTools(server, deps) {
|
|
|
169
625
|
}, async ({ runId }) => {
|
|
170
626
|
try {
|
|
171
627
|
const detail = await store.readRun(runId);
|
|
172
|
-
return textResult(
|
|
628
|
+
return textResult({
|
|
629
|
+
...projectRunForMcp(detail),
|
|
630
|
+
run_manifest: redactRunManifestForRead(detail.run_manifest),
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
catch (err) {
|
|
634
|
+
const mapped = mapStoreLookupError(err, { policy: "run" });
|
|
635
|
+
return textResult({ error: mapped.error, status: mapped.status }, true);
|
|
636
|
+
}
|
|
637
|
+
});
|
|
638
|
+
server.registerTool("export_run", {
|
|
639
|
+
description: "Export a single run as projectRun projection plus run_manifest. Works for running, cancelled, and terminal runs. Prefer over CLI sf export-run when the Host is reachable.",
|
|
640
|
+
inputSchema: z.object({
|
|
641
|
+
runId: z.string(),
|
|
642
|
+
}),
|
|
643
|
+
}, async ({ runId }) => {
|
|
644
|
+
try {
|
|
645
|
+
const detail = await store.readRun(runId);
|
|
646
|
+
return textResult(buildRunExportPayload(detail));
|
|
173
647
|
}
|
|
174
648
|
catch (err) {
|
|
175
649
|
const mapped = mapStoreLookupError(err, { policy: "run" });
|
|
@@ -222,14 +696,21 @@ export function registerCatalogTools(server, deps) {
|
|
|
222
696
|
else if (task !== undefined && task.trim())
|
|
223
697
|
scope = "task";
|
|
224
698
|
if (scope === "full") {
|
|
225
|
-
const roots = await
|
|
699
|
+
const roots = await resolveCatalogRoots({
|
|
700
|
+
store: deps.store,
|
|
701
|
+
bootCwd: deps.cwd,
|
|
702
|
+
});
|
|
226
703
|
const results = [];
|
|
227
704
|
for (const root of roots) {
|
|
228
705
|
try {
|
|
229
|
-
results.push(await validateCatalog({
|
|
706
|
+
results.push(await validateCatalog({
|
|
707
|
+
cwd: root.path,
|
|
708
|
+
scope: "full",
|
|
709
|
+
strict: strict ?? false,
|
|
710
|
+
}));
|
|
230
711
|
}
|
|
231
712
|
catch {
|
|
232
|
-
//
|
|
713
|
+
// unreadable root; skip
|
|
233
714
|
}
|
|
234
715
|
}
|
|
235
716
|
const merged = {
|
|
@@ -244,13 +725,33 @@ export function registerCatalogTools(server, deps) {
|
|
|
244
725
|
return textResult(merged);
|
|
245
726
|
}
|
|
246
727
|
const target = scope === "pipeline" ? pipeline.trim() : task.trim();
|
|
247
|
-
const
|
|
728
|
+
const roots = await resolveCatalogRoots({
|
|
729
|
+
store: deps.store,
|
|
730
|
+
bootCwd: deps.cwd,
|
|
731
|
+
});
|
|
732
|
+
let resolvedTarget = target;
|
|
733
|
+
let projectRoot = deps.cwd;
|
|
734
|
+
try {
|
|
735
|
+
const resolved = resolveCatalogRelativePath({
|
|
736
|
+
inputPath: target,
|
|
737
|
+
roots,
|
|
738
|
+
fieldName: scope === "pipeline" ? "pipeline" : "task",
|
|
739
|
+
});
|
|
740
|
+
resolvedTarget = resolved.absolutePath;
|
|
741
|
+
projectRoot = resolved.root.path;
|
|
742
|
+
}
|
|
743
|
+
catch (err) {
|
|
744
|
+
if (err instanceof CatalogPathError) {
|
|
745
|
+
return textResult(catalogPathErrorBody(err), true);
|
|
746
|
+
}
|
|
747
|
+
throw err;
|
|
748
|
+
}
|
|
248
749
|
const result = await validateCatalog({
|
|
249
750
|
cwd: projectRoot,
|
|
250
751
|
scope,
|
|
251
752
|
projectRoot,
|
|
252
|
-
...(scope === "pipeline" ? { pipeline:
|
|
253
|
-
...(scope === "task" ? { task:
|
|
753
|
+
...(scope === "pipeline" ? { pipeline: resolvedTarget } : {}),
|
|
754
|
+
...(scope === "task" ? { task: resolvedTarget } : {}),
|
|
254
755
|
strict: strict ?? false,
|
|
255
756
|
});
|
|
256
757
|
return textResult(result);
|
|
@@ -261,23 +762,37 @@ export function registerCatalogTools(server, deps) {
|
|
|
261
762
|
}
|
|
262
763
|
});
|
|
263
764
|
server.registerTool("describe_pipeline", {
|
|
264
|
-
description: "Describe a pipeline DAG from a
|
|
765
|
+
description: "Describe a pipeline DAG from a catalog-relative path (same path contract as start_run): stages with inbound needs (id, on, optional if), fork, gate_kinds, Clone Chain clone_cap and clone_mode, and feedback_loop, entry, and replay_safe when set.",
|
|
265
766
|
inputSchema: z.object({
|
|
266
767
|
pipeline: z.string(),
|
|
768
|
+
project_root: z.string().optional(),
|
|
267
769
|
}),
|
|
268
|
-
}, async ({ pipeline }) => {
|
|
770
|
+
}, async ({ pipeline, project_root }) => {
|
|
269
771
|
if (!pipeline.trim()) {
|
|
270
772
|
return textResult({ error: "pipeline is required", status: 400 }, true);
|
|
271
773
|
}
|
|
272
774
|
try {
|
|
273
|
-
const
|
|
274
|
-
|
|
775
|
+
const roots = await resolveCatalogRoots({
|
|
776
|
+
store: deps.store,
|
|
777
|
+
bootCwd: deps.cwd,
|
|
778
|
+
});
|
|
779
|
+
const resolved = resolveCatalogRelativePath({
|
|
780
|
+
inputPath: pipeline.trim(),
|
|
781
|
+
projectRoot: project_root,
|
|
782
|
+
roots,
|
|
783
|
+
fieldName: "pipeline",
|
|
784
|
+
});
|
|
785
|
+
const loaded = await loadPipeline(resolved.absolutePath, {
|
|
786
|
+
projectRoot: resolved.root.path,
|
|
275
787
|
});
|
|
276
788
|
return textResult(describePipeline(loaded));
|
|
277
789
|
}
|
|
278
790
|
catch (err) {
|
|
791
|
+
if (err instanceof CatalogPathError) {
|
|
792
|
+
return textResult(catalogPathErrorBody(err), true);
|
|
793
|
+
}
|
|
279
794
|
const message = err instanceof Error ? err.message : String(err);
|
|
280
|
-
return textResult({ error: message, status:
|
|
795
|
+
return textResult({ error: message, status: 400 }, true);
|
|
281
796
|
}
|
|
282
797
|
});
|
|
283
798
|
}
|