stageflow 0.33.0 → 0.36.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 +3 -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 +56 -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/piAdapter.d.ts +2 -2
- package/dist/agent/piAdapter.js +125 -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 +4 -2
- package/dist/agent/providerAuth.js +36 -3
- package/dist/agent/{resolveAgentPort.d.ts → resolveStagePort.d.ts} +8 -8
- package/dist/agent/{resolveAgentPort.js → resolveStagePort.js} +11 -11
- 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/channels/config.d.ts +11 -0
- package/dist/channels/config.js +95 -0
- package/dist/channels/configWriter.d.ts +40 -0
- package/dist/channels/configWriter.js +148 -0
- package/dist/channels/connectionEdits.d.ts +34 -0
- package/dist/channels/connectionEdits.js +53 -0
- package/dist/channels/errorInfo.d.ts +18 -0
- package/dist/channels/errorInfo.js +71 -0
- package/dist/channels/errors.d.ts +12 -0
- package/dist/channels/errors.js +13 -0
- package/dist/channels/health.d.ts +41 -0
- package/dist/channels/health.js +99 -0
- package/dist/channels/host.d.ts +55 -0
- package/dist/channels/host.js +185 -0
- package/dist/channels/http.d.ts +31 -0
- package/dist/channels/http.js +79 -0
- package/dist/channels/index.d.ts +10 -0
- package/dist/channels/index.js +9 -0
- package/dist/channels/ledger.d.ts +37 -0
- package/dist/channels/ledger.js +95 -0
- package/dist/channels/providers/agentmail.d.ts +26 -0
- package/dist/channels/providers/agentmail.js +81 -0
- package/dist/channels/providers/kit.d.ts +40 -0
- package/dist/channels/providers/kit.js +78 -0
- package/dist/channels/providers/photonImessage.d.ts +45 -0
- package/dist/channels/providers/photonImessage.js +152 -0
- package/dist/channels/providers/photonWhatsapp.d.ts +49 -0
- package/dist/channels/providers/photonWhatsapp.js +146 -0
- package/dist/channels/providers/slack.d.ts +25 -0
- package/dist/channels/providers/slack.js +101 -0
- package/dist/channels/providers/telegram.d.ts +21 -0
- package/dist/channels/providers/telegram.js +100 -0
- package/dist/channels/providers.d.ts +5 -0
- package/dist/channels/providers.js +22 -0
- package/dist/channels/registry.d.ts +54 -0
- package/dist/channels/registry.js +186 -0
- package/dist/channels/secretStore.d.ts +21 -0
- package/dist/channels/secretStore.js +75 -0
- package/dist/channels/secrets.d.ts +15 -0
- package/dist/channels/secrets.js +50 -0
- package/dist/channels/service.d.ts +54 -0
- package/dist/channels/service.js +307 -0
- package/dist/channels/stageChannels.d.ts +45 -0
- package/dist/channels/stageChannels.js +110 -0
- package/dist/channels/types.d.ts +142 -0
- package/dist/channels/types.js +1 -0
- package/dist/cli/browserCommand.d.ts +3 -1
- package/dist/cli/browserCommand.js +25 -20
- package/dist/cli/doctorCommand.js +3 -1
- 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 +42 -0
- package/dist/config/draftPackage.js +220 -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 +114 -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/loadOutcome.d.ts +11 -6
- package/dist/config/loadPipeline.js +27 -4
- package/dist/config/loadStage.js +17 -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.d.ts +3 -0
- package/dist/config/mergePipelineIncludes.js +30 -0
- package/dist/config/normalizePipelineStageEntry.js +10 -1
- package/dist/config/pipelineStageKeys.js +1 -0
- 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 +9 -2
- package/dist/config/validateCatalog.js +71 -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/errors/codes.d.ts +1 -1
- package/dist/errors/codes.js +1 -0
- package/dist/hosted/runtime.d.ts +2 -2
- package/dist/hosted/types.d.ts +1 -1
- package/dist/hosted/types.js +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +2 -1
- package/dist/mcp/catalogTools.js +1 -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/preflight/channelChecks.d.ts +17 -0
- package/dist/preflight/channelChecks.js +106 -0
- package/dist/preflight/pipelinePreflight.d.ts +9 -2
- package/dist/preflight/pipelinePreflight.js +9 -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/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/credentialBinding.js +14 -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/pipelineRunner.js +3 -1
- package/dist/runtime/pipelineScheduler.d.ts +2 -2
- package/dist/runtime/pipelineScheduler.js +3 -0
- package/dist/runtime/repositoryMaterialize.d.ts +1 -1
- 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 +99 -31
- 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 +26 -1
- package/dist/runtime/stageProcessLauncher.js +33 -3
- package/dist/runtime/stageRoots.js +8 -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 +10 -2
- package/dist/server/bootstrap.js +19 -1
- package/dist/server/channelRoutes.d.ts +9 -0
- package/dist/server/channelRoutes.js +88 -0
- 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 +616 -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/sendMessage.d.ts +21 -0
- package/dist/tools/sendMessage.js +25 -0
- package/dist/tools/writeStageArtifact.d.ts +9 -0
- package/dist/tools/writeStageArtifact.js +2 -47
- package/dist/types/pipeline.d.ts +5 -2
- package/dist/types/stage.d.ts +14 -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-BOhqnPNg.js +260 -0
- package/dist/ui/assets/{index-Bv4p1aPK.css → index-Clv4sJpU.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/channels-smoke/README.md +12 -0
- package/examples/channels-smoke/channels-smoke.pipeline.yaml +11 -0
- package/examples/channels-smoke/channels-smoke.task.yaml +3 -0
- package/examples/channels-smoke/send-email.yaml +32 -0
- package/examples/channels-smoke/send-text.yaml +31 -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 +8 -3
- 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
|
@@ -21,6 +21,7 @@ import { hydrateScheduleFromStore, hydratedScheduleHasRunnableWork, resumeRun, r
|
|
|
21
21
|
import { resolveFeedbackLoopDecision, } from "./feedbackLoopDecision.js";
|
|
22
22
|
import { RunRetryCoordinator, readRetryRootWaitTimeoutMs, } from "./runRetryCoordinator.js";
|
|
23
23
|
import { readMaxActiveStageProcesses, readMaxActiveStagesPerRun, readStageExecutionMode, } from "./stageConcurrency.js";
|
|
24
|
+
import { runOwnerScope } from "../browser/ownerScope.js";
|
|
24
25
|
import { isHumanLoginStage } from "../browser/humanLogin.js";
|
|
25
26
|
import { defaultStageBrowserSupport, resolveStageBrowserEnv, } from "../browser/stageBrowserEnv.js";
|
|
26
27
|
import { teardownRunBrowsers, teardownStageBrowser, } from "../browser/browserTeardown.js";
|
|
@@ -40,6 +41,7 @@ import { getContainerLimits } from "./containerLimits.js";
|
|
|
40
41
|
import { stageflowCacheRoot } from "./stageCacheEnv.js";
|
|
41
42
|
import { assertClaudeNotRoot, ClaudeRootError } from "../preflight/claudeRoot.js";
|
|
42
43
|
import { preflightFailureCode, runPipelinePreflight, } from "../preflight/pipelinePreflight.js";
|
|
44
|
+
import { channelFailureSummary } from "../preflight/channelChecks.js";
|
|
43
45
|
import { asAgentBackendId } from "../agent/agentBackend.js";
|
|
44
46
|
import { INVALID_SLOT_COUNT_MESSAGE, parseSlotCount, readMaxConcurrentFromGlobal, writeMaxConcurrentToGlobal, } from "./settingsFile.js";
|
|
45
47
|
import { StageHitlController, waitKey, } from "./stageHitl.js";
|
|
@@ -267,6 +269,9 @@ export class RunManager {
|
|
|
267
269
|
queuedDone = new Map();
|
|
268
270
|
admissionDrainInFlight = false;
|
|
269
271
|
resumeInFlight = new Set();
|
|
272
|
+
gateClosedListeners = new Set();
|
|
273
|
+
beforeBrowserTeardownListeners = new Set();
|
|
274
|
+
shutdownListeners = new Set();
|
|
270
275
|
retryInFlight = new Set();
|
|
271
276
|
retryStartOwner = new Map();
|
|
272
277
|
retryStartWaiters = new Map();
|
|
@@ -357,7 +362,18 @@ export class RunManager {
|
|
|
357
362
|
return this.active.size;
|
|
358
363
|
}
|
|
359
364
|
stopAcceptingWork() {
|
|
365
|
+
const wasAccepting = this.acceptingWork;
|
|
360
366
|
this.acceptingWork = false;
|
|
367
|
+
if (wasAccepting) {
|
|
368
|
+
for (const listener of [...this.shutdownListeners]) {
|
|
369
|
+
try {
|
|
370
|
+
listener();
|
|
371
|
+
}
|
|
372
|
+
catch {
|
|
373
|
+
// listeners must not affect shutdown
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
361
377
|
for (const halt of this.schedulingHalts.values()) {
|
|
362
378
|
halt.halted = true;
|
|
363
379
|
halt.hostShutdown = true;
|
|
@@ -592,13 +608,14 @@ export class RunManager {
|
|
|
592
608
|
.some((entry) => entry.runId === runId && entry.stageId === stageId);
|
|
593
609
|
}
|
|
594
610
|
async sweepBrowserSessions() {
|
|
595
|
-
const support = this.
|
|
611
|
+
const support = this.browserSupport();
|
|
596
612
|
const isRunLive = createRunLiveness(this.options.store);
|
|
597
613
|
await stageProfileLock(support)
|
|
598
614
|
.reclaimStale(isRunLive)
|
|
599
615
|
.catch(() => 0);
|
|
600
616
|
return sweepOrphanBrowserSessions({
|
|
601
617
|
isRunLive,
|
|
618
|
+
host: support.host,
|
|
602
619
|
...(support.runner !== undefined ? { runner: support.runner } : {}),
|
|
603
620
|
...(support.closeWaitMs !== undefined
|
|
604
621
|
? { closeWaitMs: support.closeWaitMs }
|
|
@@ -833,6 +850,64 @@ export class RunManager {
|
|
|
833
850
|
}
|
|
834
851
|
await this.drainAdmissionQueue();
|
|
835
852
|
}
|
|
853
|
+
/** Called when a stage's gate stops accepting operator input (answered, abandoned) or a run is cancelled (no stage id). */
|
|
854
|
+
onGateClosed(listener) {
|
|
855
|
+
this.gateClosedListeners.add(listener);
|
|
856
|
+
return () => {
|
|
857
|
+
this.gateClosedListeners.delete(listener);
|
|
858
|
+
};
|
|
859
|
+
}
|
|
860
|
+
/** Awaited (bounded by the browser support) before a stage's or run's browser is torn down; stageId absent means the whole run. */
|
|
861
|
+
beforeBrowserTeardown(listener) {
|
|
862
|
+
this.beforeBrowserTeardownListeners.add(listener);
|
|
863
|
+
return () => {
|
|
864
|
+
this.beforeBrowserTeardownListeners.delete(listener);
|
|
865
|
+
};
|
|
866
|
+
}
|
|
867
|
+
/** Called once the Host stops accepting work (drain start). */
|
|
868
|
+
onShutdown(listener) {
|
|
869
|
+
this.shutdownListeners.add(listener);
|
|
870
|
+
return () => {
|
|
871
|
+
this.shutdownListeners.delete(listener);
|
|
872
|
+
};
|
|
873
|
+
}
|
|
874
|
+
browserSupport() {
|
|
875
|
+
const base = this.options.browser ?? defaultStageBrowserSupport();
|
|
876
|
+
if (this.beforeBrowserTeardownListeners.size === 0)
|
|
877
|
+
return base;
|
|
878
|
+
return {
|
|
879
|
+
...base,
|
|
880
|
+
beforeTeardown: async (input) => {
|
|
881
|
+
await Promise.all([
|
|
882
|
+
base.beforeTeardown?.(input),
|
|
883
|
+
...[...this.beforeBrowserTeardownListeners].map(async (listener) => {
|
|
884
|
+
try {
|
|
885
|
+
await listener(input);
|
|
886
|
+
}
|
|
887
|
+
catch {
|
|
888
|
+
// listeners must not block teardown
|
|
889
|
+
}
|
|
890
|
+
}),
|
|
891
|
+
]);
|
|
892
|
+
},
|
|
893
|
+
};
|
|
894
|
+
}
|
|
895
|
+
browserOption() {
|
|
896
|
+
if (this.options.browser === undefined && this.beforeBrowserTeardownListeners.size === 0) {
|
|
897
|
+
return {};
|
|
898
|
+
}
|
|
899
|
+
return { browser: this.browserSupport() };
|
|
900
|
+
}
|
|
901
|
+
notifyGateClosed(runId, stageId) {
|
|
902
|
+
for (const listener of [...this.gateClosedListeners]) {
|
|
903
|
+
try {
|
|
904
|
+
listener(runId, stageId);
|
|
905
|
+
}
|
|
906
|
+
catch {
|
|
907
|
+
// listeners must not affect run control
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
}
|
|
836
911
|
async abandonStage(runId, stageId) {
|
|
837
912
|
let detail;
|
|
838
913
|
try {
|
|
@@ -863,6 +938,7 @@ export class RunManager {
|
|
|
863
938
|
status: 409,
|
|
864
939
|
};
|
|
865
940
|
}
|
|
941
|
+
this.notifyGateClosed(runId, stageId);
|
|
866
942
|
if (this.stageProcessLauncher !== undefined) {
|
|
867
943
|
const hasActive = this.stageProcessLauncher
|
|
868
944
|
.getActiveStageProcesses()
|
|
@@ -871,7 +947,7 @@ export class RunManager {
|
|
|
871
947
|
await this.stageProcessLauncher.cancelRun(runId);
|
|
872
948
|
}
|
|
873
949
|
}
|
|
874
|
-
await teardownStageBrowser(this.
|
|
950
|
+
await teardownStageBrowser(this.browserSupport(), {
|
|
875
951
|
runId,
|
|
876
952
|
runDir: this.options.store.getWorkspaceDir(runId),
|
|
877
953
|
stageId,
|
|
@@ -893,7 +969,7 @@ export class RunManager {
|
|
|
893
969
|
const hasWaiting = after.stages.some((s) => s.status === "waiting_for_input");
|
|
894
970
|
if (!hasWaiting &&
|
|
895
971
|
!(await createRunLiveness(this.options.store)(runId).catch(() => true))) {
|
|
896
|
-
await teardownRunBrowsers(this.
|
|
972
|
+
await teardownRunBrowsers(this.browserSupport(), {
|
|
897
973
|
runId,
|
|
898
974
|
runDir: this.options.store.getWorkspaceDir(runId),
|
|
899
975
|
events: (stageId) => this.options.store.listStageEvents(runId, stageId),
|
|
@@ -931,6 +1007,7 @@ export class RunManager {
|
|
|
931
1007
|
};
|
|
932
1008
|
}
|
|
933
1009
|
await this.options.store.updateRunStatus(runId, "cancelled");
|
|
1010
|
+
this.notifyGateClosed(runId);
|
|
934
1011
|
await this.options.store.setCancelReason(runId, trimmedReason);
|
|
935
1012
|
await finaliseStoredRunManifest(this.options.store, runId).catch(() => undefined);
|
|
936
1013
|
await this.refreshRunDiskBytes(runId).catch(() => undefined);
|
|
@@ -950,7 +1027,7 @@ export class RunManager {
|
|
|
950
1027
|
if (this.stageProcessLauncher !== undefined) {
|
|
951
1028
|
await this.stageProcessLauncher.cancelRun(runId);
|
|
952
1029
|
}
|
|
953
|
-
await teardownRunBrowsers(this.
|
|
1030
|
+
await teardownRunBrowsers(this.browserSupport(), {
|
|
954
1031
|
runId,
|
|
955
1032
|
runDir: this.options.store.getWorkspaceDir(runId),
|
|
956
1033
|
events: (stageId) => this.options.store.listStageEvents(runId, stageId),
|
|
@@ -1530,9 +1607,7 @@ export class RunManager {
|
|
|
1530
1607
|
agent: this.options.agent,
|
|
1531
1608
|
cwd: meta.project_root ?? this.projectRoot,
|
|
1532
1609
|
operatorCatalog: this.options.operatorCatalog,
|
|
1533
|
-
...
|
|
1534
|
-
? { browser: this.options.browser }
|
|
1535
|
-
: {}),
|
|
1610
|
+
...this.browserOption(),
|
|
1536
1611
|
maxActiveStagesPerRun: this.maxActiveStagesPerRun,
|
|
1537
1612
|
executionMode: this.executionMode,
|
|
1538
1613
|
stageProcessLauncher: this.stageProcessLauncher,
|
|
@@ -1757,6 +1832,7 @@ export class RunManager {
|
|
|
1757
1832
|
}
|
|
1758
1833
|
return prefix;
|
|
1759
1834
|
}
|
|
1835
|
+
this.notifyGateClosed(runId, stageId);
|
|
1760
1836
|
return await orchestrateAnswerResume({
|
|
1761
1837
|
prefixMode: prefix.mode,
|
|
1762
1838
|
executionMode: this.executionMode,
|
|
@@ -1896,9 +1972,7 @@ export class RunManager {
|
|
|
1896
1972
|
checkoutRoot: meta.checkout_root,
|
|
1897
1973
|
hitl: this.hitl,
|
|
1898
1974
|
operatorCatalog: this.options.operatorCatalog,
|
|
1899
|
-
...
|
|
1900
|
-
? { browser: this.options.browser }
|
|
1901
|
-
: {}),
|
|
1975
|
+
...this.browserOption(),
|
|
1902
1976
|
},
|
|
1903
1977
|
maxActiveStagesPerRun: this.maxActiveStagesPerRun,
|
|
1904
1978
|
executionMode: this.executionMode,
|
|
@@ -1957,7 +2031,8 @@ export class RunManager {
|
|
|
1957
2031
|
});
|
|
1958
2032
|
const resumedStage = loaded.stages.find((s) => s.id === definitionIdForInstance(meta.pipeline_dag, stageId));
|
|
1959
2033
|
if (resumedStage?.browser?.profile !== undefined) {
|
|
1960
|
-
await acquireStageProfile(this.
|
|
2034
|
+
await acquireStageProfile(this.browserSupport(), {
|
|
2035
|
+
scope: runOwnerScope(this.browserSupport(), { runId }),
|
|
1961
2036
|
profile: resumedStage.browser.profile,
|
|
1962
2037
|
owner: { runId, stageId },
|
|
1963
2038
|
isRunLive: createRunLiveness(store),
|
|
@@ -1968,9 +2043,10 @@ export class RunManager {
|
|
|
1968
2043
|
}
|
|
1969
2044
|
});
|
|
1970
2045
|
}
|
|
1971
|
-
const browserEnv = await resolveStageBrowserEnv(this.
|
|
2046
|
+
const browserEnv = await resolveStageBrowserEnv(this.browserSupport(), {
|
|
1972
2047
|
runId,
|
|
1973
2048
|
stageId,
|
|
2049
|
+
scope: runOwnerScope(this.browserSupport(), { runId }),
|
|
1974
2050
|
runDir: workspaceDir,
|
|
1975
2051
|
browser: resumedStage?.browser,
|
|
1976
2052
|
attempt,
|
|
@@ -1999,7 +2075,7 @@ export class RunManager {
|
|
|
1999
2075
|
if (launchResult.type === "waiting") {
|
|
2000
2076
|
return { ok: true };
|
|
2001
2077
|
}
|
|
2002
|
-
await teardownStageBrowser(this.
|
|
2078
|
+
await teardownStageBrowser(this.browserSupport(), {
|
|
2003
2079
|
runId,
|
|
2004
2080
|
runDir: workspaceDir,
|
|
2005
2081
|
stageId,
|
|
@@ -2021,9 +2097,7 @@ export class RunManager {
|
|
|
2021
2097
|
checkoutRoot: meta.checkout_root,
|
|
2022
2098
|
hitl: this.hitl,
|
|
2023
2099
|
operatorCatalog: this.options.operatorCatalog,
|
|
2024
|
-
...
|
|
2025
|
-
? { browser: this.options.browser }
|
|
2026
|
-
: {}),
|
|
2100
|
+
...this.browserOption(),
|
|
2027
2101
|
},
|
|
2028
2102
|
retryRoots: new Map([[stageId, nextRepairAttempt]]),
|
|
2029
2103
|
maxActiveStagesPerRun: this.maxActiveStagesPerRun,
|
|
@@ -2041,7 +2115,7 @@ export class RunManager {
|
|
|
2041
2115
|
reason: launchResult.reason,
|
|
2042
2116
|
}, eventOptions);
|
|
2043
2117
|
await store.updateRunStatus(runId, "failed");
|
|
2044
|
-
await teardownRunBrowsers(this.
|
|
2118
|
+
await teardownRunBrowsers(this.browserSupport(), {
|
|
2045
2119
|
runId,
|
|
2046
2120
|
runDir: workspaceDir,
|
|
2047
2121
|
events: (stageId) => store.listStageEvents(runId, stageId),
|
|
@@ -2067,9 +2141,7 @@ export class RunManager {
|
|
|
2067
2141
|
checkoutRoot: meta.checkout_root,
|
|
2068
2142
|
hitl: this.hitl,
|
|
2069
2143
|
operatorCatalog: this.options.operatorCatalog,
|
|
2070
|
-
...
|
|
2071
|
-
? { browser: this.options.browser }
|
|
2072
|
-
: {}),
|
|
2144
|
+
...this.browserOption(),
|
|
2073
2145
|
},
|
|
2074
2146
|
maxActiveStagesPerRun: this.maxActiveStagesPerRun,
|
|
2075
2147
|
resumeFromStageId: stageId,
|
|
@@ -2093,7 +2165,7 @@ export class RunManager {
|
|
|
2093
2165
|
reason,
|
|
2094
2166
|
}, eventOptions);
|
|
2095
2167
|
await store.updateRunStatus(runId, "failed");
|
|
2096
|
-
await teardownRunBrowsers(this.
|
|
2168
|
+
await teardownRunBrowsers(this.browserSupport(), {
|
|
2097
2169
|
runId,
|
|
2098
2170
|
runDir: store.getWorkspaceDir(runId),
|
|
2099
2171
|
events: (stageId) => store.listStageEvents(runId, stageId),
|
|
@@ -2260,7 +2332,9 @@ export class RunManager {
|
|
|
2260
2332
|
"missing_tool";
|
|
2261
2333
|
return {
|
|
2262
2334
|
ok: false,
|
|
2263
|
-
reason: `Pipeline preflight failed: ${code}
|
|
2335
|
+
reason: `Pipeline preflight failed: ${code}${code === "channel_check_failed" && channelFailureSummary(preflight.checks)
|
|
2336
|
+
? `: ${channelFailureSummary(preflight.checks)}`
|
|
2337
|
+
: ""}`,
|
|
2264
2338
|
status: 400,
|
|
2265
2339
|
code,
|
|
2266
2340
|
};
|
|
@@ -2406,9 +2480,7 @@ export class RunManager {
|
|
|
2406
2480
|
const started = await startPipeline({
|
|
2407
2481
|
dispatchKey,
|
|
2408
2482
|
submission,
|
|
2409
|
-
...
|
|
2410
|
-
? { browser: this.options.browser }
|
|
2411
|
-
: {}),
|
|
2483
|
+
...this.browserOption(),
|
|
2412
2484
|
agent: this.options.agent,
|
|
2413
2485
|
store: this.options.store,
|
|
2414
2486
|
taskYaml,
|
|
@@ -2911,9 +2983,7 @@ export class RunManager {
|
|
|
2911
2983
|
const schedulingHalt = this.ensureSchedulingHalt(runId);
|
|
2912
2984
|
const started = await startPipeline({
|
|
2913
2985
|
submission,
|
|
2914
|
-
...
|
|
2915
|
-
? { browser: this.options.browser }
|
|
2916
|
-
: {}),
|
|
2986
|
+
...this.browserOption(),
|
|
2917
2987
|
agent: this.options.agent,
|
|
2918
2988
|
store: this.options.store,
|
|
2919
2989
|
taskYaml,
|
|
@@ -3018,9 +3088,7 @@ export class RunManager {
|
|
|
3018
3088
|
checkoutRoot: loadedMeta.checkout_root,
|
|
3019
3089
|
hitl: this.hitl,
|
|
3020
3090
|
operatorCatalog: this.options.operatorCatalog,
|
|
3021
|
-
...
|
|
3022
|
-
? { browser: this.options.browser }
|
|
3023
|
-
: {}),
|
|
3091
|
+
...this.browserOption(),
|
|
3024
3092
|
},
|
|
3025
3093
|
maxActiveStagesPerRun: this.maxActiveStagesPerRun,
|
|
3026
3094
|
executionMode: this.executionMode,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { StagePort } from "../agent/port.js";
|
|
2
2
|
import { type RunDetail, type RunPipelineDagSnapshot, type RunStatus, type RunStore, type StageSnapshot } from "../runstore/port.js";
|
|
3
3
|
import type { PipelineRunResult } from "./pipelineRunner.js";
|
|
4
4
|
import { type SchedulerPreparedPipeline } from "./pipelineScheduler.js";
|
|
@@ -56,7 +56,7 @@ export type RetryStageRequest = {
|
|
|
56
56
|
runId: string;
|
|
57
57
|
stageId: string;
|
|
58
58
|
store: RunStore;
|
|
59
|
-
agent:
|
|
59
|
+
agent: StagePort;
|
|
60
60
|
cwd: string;
|
|
61
61
|
operatorCatalog?: OperatorCatalog;
|
|
62
62
|
browser?: StageBrowserSupport;
|
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
1
|
import { Cron } from "croner";
|
|
3
|
-
import {
|
|
4
|
-
import { loadTriggerOutcome } from "../config/loadTrigger.js";
|
|
5
|
-
import { catalogContextFromStageflow } from "../config/resolveCatalogContext.js";
|
|
6
|
-
import { resolveStageflowContext } from "../project/resolveStageflowContext.js";
|
|
2
|
+
import { listCatalogTriggerMatches, readTriggerStoreRecord, triggerStoreId, } from "../config/triggerCatalog.js";
|
|
7
3
|
export const DEFAULT_TRIGGER_TICK_INTERVAL_MS = 30_000;
|
|
8
4
|
/** Parse `STAGEFLOW_TRIGGER_TICK_INTERVAL_MS`; default 30s; `0` disables. */
|
|
9
5
|
export function triggerTickIntervalMsFromEnv(env = process.env) {
|
|
@@ -72,17 +68,14 @@ export class ScheduleSource {
|
|
|
72
68
|
* against an injected clock instead of waiting on real interval timers.
|
|
73
69
|
*/
|
|
74
70
|
async tick(onFire) {
|
|
75
|
-
const ctx = catalogContextFromStageflow(await resolveStageflowContext(this.cwd));
|
|
76
|
-
const scanPaths = await getCatalogScanPaths(ctx);
|
|
77
|
-
if (!scanPaths)
|
|
78
|
-
return;
|
|
79
71
|
const now = this.now();
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
72
|
+
const catalogTriggers = await listCatalogTriggerMatches({
|
|
73
|
+
store: this.store,
|
|
74
|
+
bootCwd: this.cwd,
|
|
75
|
+
sourceRootsOnly: true,
|
|
76
|
+
});
|
|
77
|
+
for (const match of catalogTriggers) {
|
|
78
|
+
const definition = match.definition;
|
|
86
79
|
if (definition.kind !== "schedule" || !definition.enabled || !definition.schedule) {
|
|
87
80
|
continue;
|
|
88
81
|
}
|
|
@@ -94,25 +87,23 @@ export class ScheduleSource {
|
|
|
94
87
|
this.logError(`invalid schedule for trigger "${definition.id}": ${err instanceof Error ? err.message : String(err)}`);
|
|
95
88
|
continue;
|
|
96
89
|
}
|
|
97
|
-
const
|
|
98
|
-
? path.relative(projectRoot, triggerPath).replace(/\\/g, "/")
|
|
99
|
-
: triggerPath;
|
|
90
|
+
const storeId = triggerStoreId(match.project_root, definition.id);
|
|
100
91
|
await this.store.upsertTrigger({
|
|
101
|
-
id:
|
|
102
|
-
definitionRef,
|
|
92
|
+
id: storeId,
|
|
93
|
+
definitionRef: match.definition_ref,
|
|
103
94
|
enabled: true,
|
|
104
95
|
});
|
|
105
|
-
const record = await this.store.
|
|
96
|
+
const record = await readTriggerStoreRecord(this.store, match.project_root, definition.id);
|
|
106
97
|
if (!record?.next_run_at) {
|
|
107
98
|
if (next)
|
|
108
|
-
await this.store.setTriggerNextRun(
|
|
99
|
+
await this.store.setTriggerNextRun(storeId, next.toISOString());
|
|
109
100
|
continue;
|
|
110
101
|
}
|
|
111
102
|
const dueAt = new Date(record.next_run_at);
|
|
112
103
|
if (dueAt.getTime() <= now.getTime()) {
|
|
113
|
-
await onFire({ triggerId: definition.id });
|
|
104
|
+
await onFire({ triggerId: definition.id, project_root: match.project_root });
|
|
114
105
|
if (next)
|
|
115
|
-
await this.store.setTriggerNextRun(
|
|
106
|
+
await this.store.setTriggerNextRun(storeId, next.toISOString());
|
|
116
107
|
}
|
|
117
108
|
}
|
|
118
109
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { StagePort, FeedbackLoopContext, StageHandle, StageRunInput, StageSessionMode } from "../agent/port.js";
|
|
2
2
|
import { type StageStreamLogWriter } from "./stageStreamLog.js";
|
|
3
3
|
import type { RunStore } from "../runstore/port.js";
|
|
4
4
|
import type { StageEnvelope } from "../types/envelope.js";
|
|
@@ -12,7 +12,7 @@ export type OperatorCatalog = {
|
|
|
12
12
|
agentDir?: string;
|
|
13
13
|
};
|
|
14
14
|
export type StageAttemptOpenInput = {
|
|
15
|
-
agent: Pick<
|
|
15
|
+
agent: Pick<StagePort, "openStage">;
|
|
16
16
|
store: RunStore;
|
|
17
17
|
runId: string;
|
|
18
18
|
stage: LoadedStageConfig;
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { emailHostFor, stageEmail, workerStageEmail, validateStageEmailAccounts } from "../email/host.js";
|
|
2
|
+
import { ChannelError } from "../channels/errors.js";
|
|
3
|
+
import { channelHostFor, stageChannels, validateStageChannelConnections, workerStageChannels } from "../channels/host.js";
|
|
2
4
|
import { EmailError } from "../email/port.js";
|
|
3
5
|
import { bindingKindForOrigin, catalogOrSeededOrigin, decideWorkspaceConfigTrust, } from "../config/configOrigin.js";
|
|
4
6
|
import { loginCheckPromptBlock, readStageLoginCheck, } from "../browser/loginCheck.js";
|
|
7
|
+
import { stageGateHandoff } from "../browser/stageHandoff.js";
|
|
5
8
|
import { humanLoginPromptBlock, isHumanLoginStage } from "../browser/humanLogin.js";
|
|
6
9
|
import { BROWSER_SKILL_NAME, resolveBuiltinSkillFile, } from "../config/builtinSkills.js";
|
|
7
10
|
import { resolveSkillByName, } from "../config/listSkills.js";
|
|
@@ -239,12 +242,20 @@ async function openStageWithOperatorCatalog(agent, input, catalog, factoryCwd, a
|
|
|
239
242
|
return { ok: false, reason: "browser login check result is missing" };
|
|
240
243
|
}
|
|
241
244
|
}
|
|
245
|
+
const humanLoginHandoff = humanLogin
|
|
246
|
+
? await stageGateHandoff({
|
|
247
|
+
runDir: resolveOptions.workspaceDir,
|
|
248
|
+
runId: resolveOptions.runId,
|
|
249
|
+
stageId: input.stage.id,
|
|
250
|
+
dirStageId: stageIdForManifest,
|
|
251
|
+
})
|
|
252
|
+
: undefined;
|
|
242
253
|
try {
|
|
243
254
|
const handle = agent.openStage({
|
|
244
255
|
...input,
|
|
245
256
|
stage: {
|
|
246
257
|
...input.stage,
|
|
247
|
-
system_prompt: `${stampStagePromptArtifactsDir(input.stage.system_prompt, artifactsDir)}${loginCheck !== undefined ? `\n\n${loginCheckPromptBlock(loginCheck)}` : ""}${humanLogin ? `\n\n${humanLoginPromptBlock(input.stage.browser?.login_url ?? input.stage.browser?.check?.url)}` : ""}`,
|
|
258
|
+
system_prompt: `${stampStagePromptArtifactsDir(input.stage.system_prompt, artifactsDir)}${loginCheck !== undefined ? `\n\n${loginCheckPromptBlock(loginCheck)}` : ""}${humanLogin ? `\n\n${humanLoginPromptBlock(input.stage.browser?.login_url ?? input.stage.browser?.check?.url, humanLoginHandoff?.kind === "live_view" ? "live_view" : "local_window")}` : ""}`,
|
|
248
259
|
...(loginCheck !== undefined
|
|
249
260
|
? {
|
|
250
261
|
pre_emit_checks: [
|
|
@@ -441,6 +452,16 @@ export async function openStageAttempt(input) {
|
|
|
441
452
|
throw error;
|
|
442
453
|
}
|
|
443
454
|
}
|
|
455
|
+
if (process.env.SF_STAGE_WORKER !== "1" && input.stage.channels?.length) {
|
|
456
|
+
try {
|
|
457
|
+
validateStageChannelConnections(channelHostFor(input.factoryCwd ?? process.cwd()), input.stage);
|
|
458
|
+
}
|
|
459
|
+
catch (error) {
|
|
460
|
+
if (error instanceof ChannelError)
|
|
461
|
+
return { ok: false, reason: error.code };
|
|
462
|
+
throw error;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
444
465
|
const opened = await openStageWithOperatorCatalog(input.agent, {
|
|
445
466
|
roots,
|
|
446
467
|
stage: input.stage,
|
|
@@ -456,6 +477,10 @@ export async function openStageAttempt(input) {
|
|
|
456
477
|
resumeToken,
|
|
457
478
|
email: input.stage.email?.length ? (process.env.SF_STAGE_WORKER === "1" ? workerStageEmail()
|
|
458
479
|
: stageEmail(emailHostFor(input.factoryCwd ?? process.cwd()).mailbox, input.stage, input.runId, { workspaceDir: input.workspaceDir, attempt })) : undefined,
|
|
480
|
+
...(input.stage.channels?.length ? {
|
|
481
|
+
channels: process.env.SF_STAGE_WORKER === "1" ? workerStageChannels()
|
|
482
|
+
: stageChannels(channelHostFor(input.factoryCwd ?? process.cwd()), input.stage, input.runId),
|
|
483
|
+
} : {}),
|
|
459
484
|
...(input.sessionMode !== undefined ? { sessionMode: input.sessionMode } : {}),
|
|
460
485
|
onActivity: (event) => {
|
|
461
486
|
input.onActivity?.(input.stage.browser !== undefined
|
|
@@ -4,7 +4,7 @@ import { logger as rootLogger, resolveLogMaxLineBytes, } from "../logging/logger
|
|
|
4
4
|
import { isCursorModelRef, readCursorApiKey } from "../agent/cursorProvider.js";
|
|
5
5
|
import { BROWSER_ENV_PREFIX } from "../browser/browserHost.js";
|
|
6
6
|
import { PACKAGE_VERSION } from "../package-meta.js";
|
|
7
|
-
import { PI_HOME_AUTH_PATH_ENV,
|
|
7
|
+
import { PI_HOME_AUTH_PATH_ENV, sfOwnedAuthPath } from "./credentialBinding.js";
|
|
8
8
|
import { redactString } from "../logging/redact.js";
|
|
9
9
|
import { getNamedSecrets } from "../logging/namedSecrets.js";
|
|
10
10
|
import { readMaxActiveStageProcesses, } from "./stageConcurrency.js";
|
|
@@ -13,6 +13,8 @@ import { buildStageEnvironment, isAmbientBlockedEnv, isForeverDeniedSecret, } fr
|
|
|
13
13
|
import { ensureStageCacheDirs } from "./stageCacheEnv.js";
|
|
14
14
|
import { SF_STAGE_WORKER, STAGE_WORKER_EXIT, } from "./stageWorkerProtocol.js";
|
|
15
15
|
import { emailHostFor, emailWorkerEnvironment, stageEmail, validateStageEmailAccounts } from "../email/host.js";
|
|
16
|
+
import { ChannelError } from "../channels/errors.js";
|
|
17
|
+
import { channelFault, channelHostFor, channelsWorkerEnvironment, stageChannels, validateStageChannelConnections } from "../channels/host.js";
|
|
16
18
|
import { EmailError } from "../email/port.js";
|
|
17
19
|
import { overlayStageBindingEnv, } from "./stageRoots.js";
|
|
18
20
|
function defaultStageCliEntry() {
|
|
@@ -189,6 +191,15 @@ export class StageProcessLauncher {
|
|
|
189
191
|
return { type: "failed", reason: error.code };
|
|
190
192
|
throw error;
|
|
191
193
|
}
|
|
194
|
+
try {
|
|
195
|
+
if (input.stage?.channels?.length)
|
|
196
|
+
validateStageChannelConnections(channelHostFor(input.factoryCwd ?? input.operatorCatalog?.cwd ?? input.rootDir), input.stage);
|
|
197
|
+
}
|
|
198
|
+
catch (error) {
|
|
199
|
+
if (error instanceof ChannelError)
|
|
200
|
+
return { type: "failed", reason: error.code };
|
|
201
|
+
throw error;
|
|
202
|
+
}
|
|
192
203
|
input = { ...input, stage: input.stage ? structuredClone(input.stage) : undefined };
|
|
193
204
|
const acquired = await this.waitForCapacity(input.runId);
|
|
194
205
|
if (!acquired) {
|
|
@@ -352,7 +363,7 @@ export class StageProcessLauncher {
|
|
|
352
363
|
: overlaid;
|
|
353
364
|
const childEnv = {
|
|
354
365
|
...withBrowser,
|
|
355
|
-
[PI_HOME_AUTH_PATH_ENV]:
|
|
366
|
+
[PI_HOME_AUTH_PATH_ENV]: sfOwnedAuthPath(),
|
|
356
367
|
};
|
|
357
368
|
const cursorApiKey = readCursorApiKey(hostEnv);
|
|
358
369
|
if (isCursorModelRef(input.model ?? "") &&
|
|
@@ -363,7 +374,7 @@ export class StageProcessLauncher {
|
|
|
363
374
|
}
|
|
364
375
|
const child = this.forkFn(this.cliEntry, args, {
|
|
365
376
|
cwd: input.rootDir,
|
|
366
|
-
env: emailWorkerEnvironment({ ...childEnv, [SF_STAGE_WORKER]: "1" }, emailHostFor(factoryCwd).accounts),
|
|
377
|
+
env: channelsWorkerEnvironment(emailWorkerEnvironment({ ...childEnv, [SF_STAGE_WORKER]: "1" }, emailHostFor(factoryCwd).accounts), factoryCwd),
|
|
367
378
|
stdio: ["pipe", "pipe", "pipe", "ipc"],
|
|
368
379
|
detached: true,
|
|
369
380
|
// Explicit: do not inherit Host execArgv; set heap from cgroup budget.
|
|
@@ -432,6 +443,25 @@ export class StageProcessLauncher {
|
|
|
432
443
|
})();
|
|
433
444
|
return;
|
|
434
445
|
}
|
|
446
|
+
if (!settled && request?.type === "channel.send") {
|
|
447
|
+
void (async () => {
|
|
448
|
+
if (typeof request.requestId !== "string" || request.requestId.length > 100)
|
|
449
|
+
return;
|
|
450
|
+
let response;
|
|
451
|
+
try {
|
|
452
|
+
const stage = input.stage;
|
|
453
|
+
if (!stage || settled)
|
|
454
|
+
throw new ChannelError("CHANNEL_UNAUTHORIZED");
|
|
455
|
+
response = { receipt: await stageChannels(channelHostFor(factoryCwd), stage, input.runId).send(request.input) };
|
|
456
|
+
}
|
|
457
|
+
catch (error) {
|
|
458
|
+
response = { error: channelFault(error) };
|
|
459
|
+
}
|
|
460
|
+
if (child.connected && !settled)
|
|
461
|
+
child.send({ type: "channel.response", requestId: request.requestId, ...response });
|
|
462
|
+
})();
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
435
465
|
if (!isStageWorkerResult(message))
|
|
436
466
|
return;
|
|
437
467
|
finish(resultFromWorkerMessage(message));
|
|
@@ -3,7 +3,8 @@ import path from "node:path";
|
|
|
3
3
|
import { isCursorModelRef } from "../agent/cursorProvider.js";
|
|
4
4
|
import { stageDir } from "../runstore/paths.js";
|
|
5
5
|
import { noAttemptContext } from "./stageAttemptContext.js";
|
|
6
|
-
import { resolveCredentialBinding, currentExplicitAuthPath } from "./credentialBinding.js";
|
|
6
|
+
import { resolveCredentialBinding, STAGEFLOW_AGENT_AUTH_PATH_ENV, currentExplicitAuthPath, } from "./credentialBinding.js";
|
|
7
|
+
import { SF_STAGE_WORKER } from "./stageWorkerProtocol.js";
|
|
7
8
|
export const STAGEFLOW_CHECKOUT = "STAGEFLOW_CHECKOUT";
|
|
8
9
|
export const STAGEFLOW_RUN_WORKSPACE = "STAGEFLOW_RUN_WORKSPACE";
|
|
9
10
|
export const STAGEFLOW_REPOSITORY = "STAGEFLOW_REPOSITORY";
|
|
@@ -131,6 +132,12 @@ export function withResolvedAuthPath(roots, factoryCwd) {
|
|
|
131
132
|
if (explicit !== undefined) {
|
|
132
133
|
return { ...roots, authPath: explicit };
|
|
133
134
|
}
|
|
135
|
+
if (process.env[SF_STAGE_WORKER] === "1") {
|
|
136
|
+
const stamped = process.env[STAGEFLOW_AGENT_AUTH_PATH_ENV]?.trim();
|
|
137
|
+
if (!stamped)
|
|
138
|
+
return roots;
|
|
139
|
+
return { ...roots, authPath: path.resolve(stamped) };
|
|
140
|
+
}
|
|
134
141
|
const binding = resolveCredentialBinding(factoryCwd);
|
|
135
142
|
return { ...roots, authPath: binding.authPath };
|
|
136
143
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { StagePort, FeedbackLoopContext, StageHandle, StageRunResult, StageSessionMode } from "../agent/port.js";
|
|
2
2
|
import { type HostGateContext } from "../browser/gateHandoff.js";
|
|
3
3
|
import type { StageBrowserSupport } from "../browser/browserHost.js";
|
|
4
4
|
import type { StageEnvelope } from "../types/envelope.js";
|
|
@@ -20,7 +20,7 @@ export declare function isRunStageWaiting(outcome: RunStageOutcome): outcome is
|
|
|
20
20
|
waiting: true;
|
|
21
21
|
};
|
|
22
22
|
export type RunStageOptions = {
|
|
23
|
-
agent:
|
|
23
|
+
agent: StagePort;
|
|
24
24
|
store: RunStore;
|
|
25
25
|
runId: string;
|
|
26
26
|
stage: LoadedStageConfig;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { stampGateRequest } from "../browser/gateHandoff.js";
|
|
2
|
+
import { stageGateContext } from "../browser/stageHandoff.js";
|
|
2
3
|
import { deriveExecutionPatchFromEvent } from "../runstore/stageExecution.js";
|
|
3
4
|
import { buildStageRoots, withResolvedAuthPath, } from "./stageRoots.js";
|
|
4
5
|
import { createDefaultHitlQaHooks, recordWaitEnter, } from "./stageHitl.js";
|
|
@@ -231,7 +232,12 @@ export async function runStage(options) {
|
|
|
231
232
|
store: workerMode ? store : undefined,
|
|
232
233
|
attemptCtx,
|
|
233
234
|
skipGates,
|
|
234
|
-
gateContext:
|
|
235
|
+
gateContext: await stageGateContext({
|
|
236
|
+
runDir: workspaceDir ?? store.getWorkspaceDir(runId),
|
|
237
|
+
runId,
|
|
238
|
+
stageId,
|
|
239
|
+
browser: stage.browser,
|
|
240
|
+
}),
|
|
235
241
|
});
|
|
236
242
|
}
|
|
237
243
|
catch (err) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { resolveStagePort } from "../agent/resolveStagePort.js";
|
|
2
2
|
import { asAgentBackendId } from "../agent/agentBackend.js";
|
|
3
3
|
import { loadStageflowManifestOutcome } from "../config/loadStageflowManifest.js";
|
|
4
4
|
import { loadNamedSecretsFromAttemptDir } from "../logging/namedSecrets.js";
|
|
@@ -29,7 +29,7 @@ export async function runStageWorker(input) {
|
|
|
29
29
|
}
|
|
30
30
|
const dag = meta.pipeline_dag ?? loaded.dag;
|
|
31
31
|
const manifestOutcome = await loadStageflowManifestOutcome(input.rootDir);
|
|
32
|
-
const agent =
|
|
32
|
+
const agent = resolveStagePort({
|
|
33
33
|
global: manifestOutcome.ok
|
|
34
34
|
? asAgentBackendId(manifestOutcome.value.manifest.agent)
|
|
35
35
|
: undefined,
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import type { TaskFile } from "../types/task.js";
|
|
2
2
|
export type TriggerFireEvent = {
|
|
3
3
|
triggerId: string;
|
|
4
|
+
project_root?: string;
|
|
4
5
|
task?: TaskFile;
|
|
5
6
|
};
|
|
6
7
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
8
|
+
* Long-running sources that decide "fire trigger X now". ScheduleSource,
|
|
9
|
+
* GithubPollSource, and EmailSource implement this. Webhook deliveries are
|
|
10
|
+
* request-driven: acceptWebhook shares TriggerFireEvent's optional task, and
|
|
11
|
+
* the HTTP route fires; a webhook is not a start/stop loop.
|
|
10
12
|
*/
|
|
11
13
|
export interface TriggerSourcePort {
|
|
12
14
|
start(onFire: (event: TriggerFireEvent) => Promise<void>): Promise<void>;
|