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
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
1
|
import { catalogContextFromStageflow } from "../config/resolveCatalogContext.js";
|
|
3
2
|
import { getCatalogScanPaths } from "../config/browseCatalog.js";
|
|
4
3
|
import { resolveStageflowContext } from "../project/resolveStageflowContext.js";
|
|
5
|
-
import { findCatalogPathById
|
|
4
|
+
import { findCatalogPathById } from "./triggerCatalog.js";
|
|
5
|
+
import { findCatalogTrigger, triggerStoreId, } from "../config/triggerCatalog.js";
|
|
6
6
|
/**
|
|
7
7
|
* Resolves a trigger id to its `*.trigger.yaml` catalog definition, resolves its
|
|
8
8
|
* `pipeline`/`task` refs to catalog files, and starts a real run through
|
|
@@ -14,17 +14,22 @@ import { findCatalogPathById, findTriggerDefinition } from "./triggerCatalog.js"
|
|
|
14
14
|
* dynamic-mode trigger (`task` absent) requires one.
|
|
15
15
|
*/
|
|
16
16
|
export async function fireTrigger(triggerId, store, runManager, options = {}) {
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
if (!
|
|
25
|
-
return {
|
|
17
|
+
const bootCwd = options.cwd ?? process.cwd();
|
|
18
|
+
const located = await findCatalogTrigger({
|
|
19
|
+
store,
|
|
20
|
+
bootCwd,
|
|
21
|
+
triggerId,
|
|
22
|
+
projectRootFilter: options.project_root,
|
|
23
|
+
});
|
|
24
|
+
if (!located.ok) {
|
|
25
|
+
return {
|
|
26
|
+
ok: false,
|
|
27
|
+
reason: located.reason,
|
|
28
|
+
status: located.status,
|
|
29
|
+
};
|
|
26
30
|
}
|
|
27
|
-
const {
|
|
31
|
+
const { match } = located;
|
|
32
|
+
const trigger = match.definition;
|
|
28
33
|
if (!trigger.enabled) {
|
|
29
34
|
return { ok: false, reason: `Trigger is disabled: ${triggerId}`, status: 409 };
|
|
30
35
|
}
|
|
@@ -45,6 +50,11 @@ export async function fireTrigger(triggerId, store, runManager, options = {}) {
|
|
|
45
50
|
code: "trigger.task_required",
|
|
46
51
|
};
|
|
47
52
|
}
|
|
53
|
+
const ctx = catalogContextFromStageflow(await resolveStageflowContext(match.rootPath));
|
|
54
|
+
const scanPaths = await getCatalogScanPaths(ctx);
|
|
55
|
+
if (!scanPaths) {
|
|
56
|
+
return { ok: false, reason: "No Stageflow catalog found", status: 404 };
|
|
57
|
+
}
|
|
48
58
|
const pipelinePath = await findCatalogPathById(scanPaths.pipelinePaths, trigger.pipeline);
|
|
49
59
|
if (!pipelinePath) {
|
|
50
60
|
return {
|
|
@@ -68,22 +78,19 @@ export async function fireTrigger(triggerId, store, runManager, options = {}) {
|
|
|
68
78
|
else {
|
|
69
79
|
taskInput = suppliedTask;
|
|
70
80
|
}
|
|
71
|
-
const
|
|
72
|
-
const definitionRef = projectRoot !== undefined
|
|
73
|
-
? path.relative(projectRoot, triggerPath).replace(/\\/g, "/")
|
|
74
|
-
: triggerPath;
|
|
81
|
+
const storeId = triggerStoreId(match.project_root, trigger.id);
|
|
75
82
|
await store.upsertTrigger({
|
|
76
|
-
id:
|
|
77
|
-
definitionRef,
|
|
83
|
+
id: storeId,
|
|
84
|
+
definitionRef: match.definition_ref,
|
|
78
85
|
enabled: trigger.enabled,
|
|
79
86
|
});
|
|
80
87
|
const started = await runManager.startRun({
|
|
81
88
|
pipeline: pipelinePath,
|
|
82
89
|
task: taskInput,
|
|
83
|
-
|
|
90
|
+
projectRoot: match.rootPath,
|
|
84
91
|
});
|
|
85
92
|
if (started.ok) {
|
|
86
|
-
await store.recordTriggerFired(
|
|
93
|
+
await store.recordTriggerFired(storeId, started.runId);
|
|
87
94
|
}
|
|
88
95
|
return started;
|
|
89
96
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { TaskFile } from "../types/task.js";
|
|
2
|
+
import type { TriggerFile } from "../types/trigger.js";
|
|
3
|
+
export type WebhookHeaderMap = {
|
|
4
|
+
readonly [name: string]: string | string[] | undefined;
|
|
5
|
+
};
|
|
6
|
+
export type WebhookAcceptResult = {
|
|
7
|
+
kind: "not_configured";
|
|
8
|
+
} | {
|
|
9
|
+
kind: "bad_signature";
|
|
10
|
+
} | {
|
|
11
|
+
kind: "bad_json";
|
|
12
|
+
error: "Invalid JSON body" | "Invalid JSON body: expected an object";
|
|
13
|
+
} | {
|
|
14
|
+
kind: "no_match";
|
|
15
|
+
} | {
|
|
16
|
+
kind: "fire";
|
|
17
|
+
task?: TaskFile;
|
|
18
|
+
};
|
|
19
|
+
export declare function acceptWebhook(input: {
|
|
20
|
+
trigger: TriggerFile;
|
|
21
|
+
rawBody: Buffer;
|
|
22
|
+
headers: WebhookHeaderMap;
|
|
23
|
+
env: NodeJS.ProcessEnv;
|
|
24
|
+
now?: () => number;
|
|
25
|
+
}): WebhookAcceptResult;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { readSecretFromEnvOrFile } from "../config/secretFromEnvOrFile.js";
|
|
2
|
+
import { matchesEventFilter } from "./triggerEventMatch.js";
|
|
3
|
+
import { verifyHmacSignature } from "./webhookSignature.js";
|
|
4
|
+
export function acceptWebhook(input) {
|
|
5
|
+
const { trigger, rawBody, headers, env } = input;
|
|
6
|
+
const now = input.now ?? Date.now;
|
|
7
|
+
const config = trigger.event?.config;
|
|
8
|
+
const secretRef = typeof config?.secretRef === "string" ? config.secretRef : undefined;
|
|
9
|
+
const header = typeof config?.header === "string" ? config.header : undefined;
|
|
10
|
+
if (secretRef === undefined || header === undefined) {
|
|
11
|
+
return { kind: "not_configured" };
|
|
12
|
+
}
|
|
13
|
+
const scheme = config?.scheme === "base64" ? "base64" : "hex";
|
|
14
|
+
let secret;
|
|
15
|
+
try {
|
|
16
|
+
secret = readSecretFromEnvOrFile(env, secretRef);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
secret = undefined;
|
|
20
|
+
}
|
|
21
|
+
if (secret === undefined) {
|
|
22
|
+
return { kind: "not_configured" };
|
|
23
|
+
}
|
|
24
|
+
const headerValue = headers[header.toLowerCase()];
|
|
25
|
+
const signature = Array.isArray(headerValue) ? headerValue[0] : headerValue;
|
|
26
|
+
if (typeof signature !== "string" ||
|
|
27
|
+
signature.length === 0 ||
|
|
28
|
+
!verifyHmacSignature(rawBody, signature, secret, scheme)) {
|
|
29
|
+
return { kind: "bad_signature" };
|
|
30
|
+
}
|
|
31
|
+
let payload;
|
|
32
|
+
try {
|
|
33
|
+
payload = rawBody.length === 0 ? {} : JSON.parse(rawBody.toString("utf8"));
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return { kind: "bad_json", error: "Invalid JSON body" };
|
|
37
|
+
}
|
|
38
|
+
if (payload === null || typeof payload !== "object" || Array.isArray(payload)) {
|
|
39
|
+
return { kind: "bad_json", error: "Invalid JSON body: expected an object" };
|
|
40
|
+
}
|
|
41
|
+
const payloadRecord = payload;
|
|
42
|
+
if (!matchesEventFilter(trigger.event?.match, payloadRecord)) {
|
|
43
|
+
return { kind: "no_match" };
|
|
44
|
+
}
|
|
45
|
+
if (trigger.task !== undefined) {
|
|
46
|
+
return { kind: "fire" };
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
kind: "fire",
|
|
50
|
+
task: {
|
|
51
|
+
id: `${trigger.id}-webhook-${now()}`,
|
|
52
|
+
goal: `Handle webhook event for trigger "${trigger.id}"`,
|
|
53
|
+
input: payloadRecord,
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
}
|
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
import { type A2aHost } from "../a2a/server.js";
|
|
2
|
-
import type {
|
|
2
|
+
import type { StagePort } from "../agent/port.js";
|
|
3
3
|
import type { ProviderAuthContext } from "../agent/providerAuth.js";
|
|
4
4
|
import { type RunStoreKind } from "../runstore/createStore.js";
|
|
5
|
+
import { type WorkspaceProvisionResult } from "../project/workspaceCatalog.js";
|
|
5
6
|
import type { RunStore } from "../runstore/port.js";
|
|
6
7
|
import type { StoreFilesystemClassification } from "../runstore/storeFilesystem.js";
|
|
8
|
+
import type { StageBrowserSupport } from "../browser/browserHost.js";
|
|
7
9
|
import { RunManager } from "../runtime/runManager.js";
|
|
8
10
|
import { emailHostFor } from "../email/host.js";
|
|
9
11
|
import { EmailTriggers } from "../email/triggers.js";
|
|
12
|
+
import { type ChannelService } from "../channels/service.js";
|
|
10
13
|
import { type RunChangeBus } from "../runtime/runChangeBus.js";
|
|
11
14
|
import { type McpHttpHandler } from "../mcp/server.js";
|
|
12
15
|
import { type HostConfig } from "../config/hostConfig.js";
|
|
13
16
|
import { bootProviderConfig } from "../agent/bootProviderConfig.js";
|
|
14
17
|
export declare const DEFAULT_GC_INTERVAL_MS: number;
|
|
15
18
|
export type StageflowHostOptions = {
|
|
16
|
-
agent:
|
|
19
|
+
agent: StagePort;
|
|
17
20
|
cwd?: string;
|
|
18
21
|
agentDir?: string;
|
|
19
22
|
rootDir?: string;
|
|
@@ -27,6 +30,8 @@ export type StageflowHostOptions = {
|
|
|
27
30
|
hostConfig?: HostConfig;
|
|
28
31
|
/** Skip HostConfig load (tests that inject store/manager pieces only). */
|
|
29
32
|
skipHostConfig?: boolean;
|
|
33
|
+
/** Browser support for the runs this Host executes; defaults to the local host with the live view relay. */
|
|
34
|
+
browser?: StageBrowserSupport;
|
|
30
35
|
emailTriggerQueue?: ConstructorParameters<typeof EmailTriggers>[0]["queue"];
|
|
31
36
|
};
|
|
32
37
|
export type StageflowHostBootstrap = {
|
|
@@ -48,12 +53,15 @@ export type StageflowHostBootstrap = {
|
|
|
48
53
|
/** Periodic retention GC handle when enabled; already `.unref()`'d. */
|
|
49
54
|
gcInterval?: NodeJS.Timeout;
|
|
50
55
|
stopGcInterval: () => void;
|
|
56
|
+
workspaceCatalog?: WorkspaceProvisionResult;
|
|
51
57
|
/** Stops the schedule-trigger tick loop started at boot. */
|
|
52
58
|
stopScheduleSource: () => void;
|
|
53
59
|
/** Stops the GitHub poll-trigger loop started at boot. */
|
|
54
60
|
stopGithubPollSource: () => void;
|
|
55
61
|
/** Stops the email-trigger IMAP/IDLE listeners started at boot. */
|
|
56
62
|
stopEmailSource: () => void;
|
|
63
|
+
/** Connections page read model and background health checks. */
|
|
64
|
+
channels?: ChannelService;
|
|
57
65
|
email?: ReturnType<typeof emailHostFor> & {
|
|
58
66
|
triggers: EmailTriggers;
|
|
59
67
|
stop: () => Promise<void>;
|
package/dist/server/bootstrap.js
CHANGED
|
@@ -4,12 +4,15 @@ import { createA2aHost } from "../a2a/server.js";
|
|
|
4
4
|
import { A2aStore } from "../a2a/store.js";
|
|
5
5
|
import { createRunStoreWithConnection } from "../runstore/createStore.js";
|
|
6
6
|
import { resolveA2aConfigPath } from "../a2a/configDiscovery.js";
|
|
7
|
-
import {
|
|
7
|
+
import { ensureProjectRootsFromEnv } from "../project/ensureProjectRootsFromEnv.js";
|
|
8
|
+
import { ensureGlobalHome, globalStageflowHome } from "../project/globalHome.js";
|
|
9
|
+
import { ensureWorkspaceCatalog, } from "../project/workspaceCatalog.js";
|
|
8
10
|
import { resolveStageflowContext } from "../project/resolveStageflowContext.js";
|
|
9
11
|
import { findProjectRoot } from "../project/findProjectRoot.js";
|
|
10
12
|
import { warnDurableRootDiskIfNeeded } from "../runstore/diskUsage.js";
|
|
11
13
|
import { assertStoreFilesystemSupported } from "../runstore/storeFilesystem.js";
|
|
12
14
|
import { assertStoreQuickCheck, isSqliteCorruptError, maybeCheckpointResidualWal, rethrowAsStoreIntegrityFailed, } from "../runstore/sqlite/applyStorePragmas.js";
|
|
15
|
+
import { consoleStageBrowserSupport } from "../browser/stageBrowserEnv.js";
|
|
13
16
|
import { RunManager } from "../runtime/runManager.js";
|
|
14
17
|
import { PI_CODING_AGENT_DIR_ENV } from "../runtime/stageRoots.js";
|
|
15
18
|
import { ScheduleSource, triggerTickIntervalMsFromEnv, } from "../runtime/scheduleSource.js";
|
|
@@ -17,6 +20,7 @@ import { GithubPollSource, githubPollIntervalMsFromEnv, } from "../runtime/githu
|
|
|
17
20
|
import { EmailSource } from "../runtime/emailSource.js";
|
|
18
21
|
import { emailHostFor, releaseEmailHost } from "../email/host.js";
|
|
19
22
|
import { EmailTriggers } from "../email/triggers.js";
|
|
23
|
+
import { startChannelService } from "../channels/service.js";
|
|
20
24
|
import { fireTrigger } from "../runtime/triggerRunner.js";
|
|
21
25
|
import { createRunChangeBus, getRunChangeBusFromWrappedStore, isRunStoreWrapped, wrapRunStoreWithChangeBus, } from "../runtime/runChangeBus.js";
|
|
22
26
|
import { createMcpHttpHandler, resolveMcpStateless, } from "../mcp/server.js";
|
|
@@ -82,6 +86,7 @@ export async function bootstrapStageflowHost(options) {
|
|
|
82
86
|
const invocationCwd = options.cwd ?? process.cwd();
|
|
83
87
|
const ctx = await resolveStageflowContext(invocationCwd);
|
|
84
88
|
const cwd = ctx.invocationCwd;
|
|
89
|
+
void globalStageflowHome();
|
|
85
90
|
ensureGlobalHome();
|
|
86
91
|
const cursorKey = readCursorApiKey(env);
|
|
87
92
|
if (cursorKey !== undefined &&
|
|
@@ -227,6 +232,11 @@ export async function bootstrapStageflowHost(options) {
|
|
|
227
232
|
}
|
|
228
233
|
const runChangeBus = options.runChangeBus ?? boundBus ?? createRunChangeBus();
|
|
229
234
|
const store = wrapRunStoreWithChangeBus(rawStore, runChangeBus);
|
|
235
|
+
await ensureProjectRootsFromEnv(env, store);
|
|
236
|
+
const workspaceCatalog = ensureWorkspaceCatalog(ctx.globalHome);
|
|
237
|
+
if (!workspaceCatalog.ok) {
|
|
238
|
+
bootLog.warn("workspace.provision_failed", workspaceCatalog.reason ?? "unknown");
|
|
239
|
+
}
|
|
230
240
|
const manager = new RunManager({
|
|
231
241
|
agent: options.agent,
|
|
232
242
|
cwd,
|
|
@@ -245,6 +255,7 @@ export async function bootstrapStageflowHost(options) {
|
|
|
245
255
|
])),
|
|
246
256
|
operatorCatalog: { cwd, agentDir },
|
|
247
257
|
a2aStore,
|
|
258
|
+
browser: options.browser ?? consoleStageBrowserSupport(),
|
|
248
259
|
});
|
|
249
260
|
await manager.attachWaitingStages();
|
|
250
261
|
await manager.reconcileOrphanedStages();
|
|
@@ -269,6 +280,9 @@ export async function bootstrapStageflowHost(options) {
|
|
|
269
280
|
const result = await fireTrigger(event.triggerId, store, manager, {
|
|
270
281
|
cwd,
|
|
271
282
|
task: event.task,
|
|
283
|
+
...(event.project_root !== undefined
|
|
284
|
+
? { project_root: event.project_root }
|
|
285
|
+
: {}),
|
|
272
286
|
});
|
|
273
287
|
if (!result.ok) {
|
|
274
288
|
bootLog.error("trigger.fire_failed", `trigger "${event.triggerId}" fire failed: ${result.reason}`);
|
|
@@ -318,9 +332,11 @@ export async function bootstrapStageflowHost(options) {
|
|
|
318
332
|
await Promise.all([stopAccountEmail(), emailSource.stop(), scheduleSource.stop(), githubPollSource.stop()]);
|
|
319
333
|
throw error;
|
|
320
334
|
}
|
|
335
|
+
const channels = startChannelService(cwd);
|
|
321
336
|
const stopEmailSource = () => {
|
|
322
337
|
void emailSource.stop();
|
|
323
338
|
void stopAccountEmail();
|
|
339
|
+
void channels.stop();
|
|
324
340
|
};
|
|
325
341
|
const mcpStateless = resolveMcpStateless({
|
|
326
342
|
mcpStateless: options.mcpStateless,
|
|
@@ -361,6 +377,8 @@ export async function bootstrapStageflowHost(options) {
|
|
|
361
377
|
stopGithubPollSource,
|
|
362
378
|
stopEmailSource,
|
|
363
379
|
email: { ...emailHost, triggers: emailTriggers, stop: stopAccountEmail },
|
|
380
|
+
channels,
|
|
364
381
|
storeFilesystem,
|
|
382
|
+
workspaceCatalog,
|
|
365
383
|
};
|
|
366
384
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
2
|
+
import type { ChannelService } from "../channels/service.js";
|
|
3
|
+
type Json = (res: ServerResponse, status: number, body: unknown) => void;
|
|
4
|
+
/**
|
|
5
|
+
* Listing, live checks and edits. Request bodies carry secret values on the way in only; nothing
|
|
6
|
+
* the API returns contains one, and failures answer with a code, never the request or its values.
|
|
7
|
+
*/
|
|
8
|
+
export declare function handleChannelRoutes(req: IncomingMessage, method: string, pathname: string, service: ChannelService, res: ServerResponse, json: Json): Promise<boolean>;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { ChannelError } from "../channels/errors.js";
|
|
2
|
+
import { channelErrorStatus } from "../channels/errorInfo.js";
|
|
3
|
+
const MAX_BODY_BYTES = 65536;
|
|
4
|
+
async function readBody(req) {
|
|
5
|
+
const chunks = [];
|
|
6
|
+
let size = 0;
|
|
7
|
+
for await (const chunk of req) {
|
|
8
|
+
const buffer = typeof chunk === "string" ? Buffer.from(chunk) : chunk;
|
|
9
|
+
size += buffer.length;
|
|
10
|
+
if (size > MAX_BODY_BYTES)
|
|
11
|
+
throw new ChannelError("CHANNEL_RESOURCE_LIMIT");
|
|
12
|
+
chunks.push(buffer);
|
|
13
|
+
}
|
|
14
|
+
if (chunks.length === 0)
|
|
15
|
+
return {};
|
|
16
|
+
try {
|
|
17
|
+
return JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
throw new ChannelError("CHANNEL_INVALID_INPUT");
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Listing, live checks and edits. Request bodies carry secret values on the way in only; nothing
|
|
25
|
+
* the API returns contains one, and failures answer with a code, never the request or its values.
|
|
26
|
+
*/
|
|
27
|
+
export async function handleChannelRoutes(req, method, pathname, service, res, json) {
|
|
28
|
+
const idMatch = pathname.match(/^\/api\/connections\/([^/]+)(?:\/(check|validate-target))?$/);
|
|
29
|
+
const isCollection = pathname === "/api/connections";
|
|
30
|
+
const isTest = pathname === "/api/connections/test";
|
|
31
|
+
const isMeta = pathname === "/api/connections/meta";
|
|
32
|
+
if (!isCollection && !isTest && !isMeta && !idMatch)
|
|
33
|
+
return false;
|
|
34
|
+
try {
|
|
35
|
+
if (isMeta && method === "GET") {
|
|
36
|
+
json(res, 200, service.meta());
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
if (isCollection && method === "GET") {
|
|
40
|
+
json(res, 200, service.list());
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
if (isCollection && method === "POST") {
|
|
44
|
+
json(res, 201, await service.create(await readBody(req)));
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
if (isTest && method === "POST") {
|
|
48
|
+
json(res, 200, await service.test(await readBody(req)));
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
if (idMatch) {
|
|
52
|
+
let id;
|
|
53
|
+
try {
|
|
54
|
+
id = decodeURIComponent(idMatch[1]);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
throw new ChannelError("CHANNEL_INVALID_INPUT");
|
|
58
|
+
}
|
|
59
|
+
if (idMatch[2] === "check" && method === "POST") {
|
|
60
|
+
const health = await service.checkNow(id);
|
|
61
|
+
if (health)
|
|
62
|
+
json(res, 200, health);
|
|
63
|
+
else
|
|
64
|
+
json(res, 404, { code: "CHANNEL_NOT_FOUND" });
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
if (idMatch[2] === "validate-target" && method === "POST") {
|
|
68
|
+
json(res, 200, service.validateTarget(id, await readBody(req)));
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
if (!idMatch[2] && method === "PATCH") {
|
|
72
|
+
json(res, 200, await service.update(id, await readBody(req)));
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
if (!idMatch[2] && method === "DELETE") {
|
|
76
|
+
await service.remove(id);
|
|
77
|
+
json(res, 200, { removed: true });
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
const code = error instanceof ChannelError ? error.code : "CHANNEL_STORAGE_FAILED";
|
|
84
|
+
json(res, channelErrorStatus(code), { code });
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
@@ -27,7 +27,7 @@ export declare function hasDriveToken(tokens: ControlTokens): boolean;
|
|
|
27
27
|
export declare function hasAnyToken(tokens: ControlTokens): boolean;
|
|
28
28
|
export declare function isLoopbackBind(bind: string): boolean;
|
|
29
29
|
export declare function refuseBindMessage(bind: string): string;
|
|
30
|
-
export declare function assertBindAllowed(bind: string, tokens: ControlTokens): void;
|
|
30
|
+
export declare function assertBindAllowed(bind: string, tokens: ControlTokens, env?: NodeJS.ProcessEnv): void;
|
|
31
31
|
export declare class BindRefusedError extends Error {
|
|
32
32
|
readonly exitCode = 1;
|
|
33
33
|
constructor(message: string);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createHash, timingSafeEqual } from "node:crypto";
|
|
2
2
|
import { readSecretFromEnvOrFile } from "../config/secretFromEnvOrFile.js";
|
|
3
3
|
import { isLoopbackHostname } from "./allowedHosts.js";
|
|
4
|
+
import { matchLiveViewRoute } from "./liveViewPath.js";
|
|
4
5
|
const CONTROL_TOKEN_PREFIX = "STAGEFLOW_CONTROL_TOKEN_";
|
|
5
6
|
const DEFAULT_CALLER_ID = "default";
|
|
6
7
|
function digest(value) {
|
|
@@ -144,9 +145,14 @@ Set one of:
|
|
|
144
145
|
STAGEFLOW_CONTROL_TOKEN_<NAME>=<at least 32 characters>
|
|
145
146
|
|
|
146
147
|
Or bind to loopback instead:
|
|
147
|
-
--host 127.0.0.1 (or unset STAGEFLOW_BIND)
|
|
148
|
+
--host 127.0.0.1 (or unset STAGEFLOW_BIND)
|
|
149
|
+
|
|
150
|
+
Or, only when the published port stays on this machine:
|
|
151
|
+
STAGEFLOW_ALLOW_UNAUTHENTICATED_BIND=1`;
|
|
148
152
|
}
|
|
149
|
-
export function assertBindAllowed(bind, tokens) {
|
|
153
|
+
export function assertBindAllowed(bind, tokens, env = process.env) {
|
|
154
|
+
if (env.STAGEFLOW_ALLOW_UNAUTHENTICATED_BIND === "1")
|
|
155
|
+
return;
|
|
150
156
|
if (!isLoopbackBind(bind) && !hasDriveToken(tokens)) {
|
|
151
157
|
throw new BindRefusedError(refuseBindMessage(bind));
|
|
152
158
|
}
|
|
@@ -169,6 +175,14 @@ export class BindRefusedError extends Error {
|
|
|
169
175
|
function isTriggerWebhookRoute(method, pathname) {
|
|
170
176
|
return method === "POST" && /^\/api\/triggers\/[^/]+\/webhook$/.test(pathname);
|
|
171
177
|
}
|
|
178
|
+
/**
|
|
179
|
+
* Live view routes authenticate themselves: the ticket route checks the bearer
|
|
180
|
+
* scope for the requested mode, and the browser's event stream and input posts
|
|
181
|
+
* carry a ticket-derived cookie instead of a bearer token.
|
|
182
|
+
*/
|
|
183
|
+
function isLiveViewRoute(pathname) {
|
|
184
|
+
return matchLiveViewRoute(pathname) !== null;
|
|
185
|
+
}
|
|
172
186
|
export function requiredScopeFor(method, pathname) {
|
|
173
187
|
if (pathname === "/mcp")
|
|
174
188
|
return "drive";
|
|
@@ -176,6 +190,8 @@ export function requiredScopeFor(method, pathname) {
|
|
|
176
190
|
return null;
|
|
177
191
|
if (isTriggerWebhookRoute(method, pathname))
|
|
178
192
|
return null;
|
|
193
|
+
if (isLiveViewRoute(pathname))
|
|
194
|
+
return null;
|
|
179
195
|
if (pathname === "/api/backup" || pathname.startsWith("/api/backup/")) {
|
|
180
196
|
return "drive";
|
|
181
197
|
}
|
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
2
|
+
import { type CatalogRoot, type ResolveCatalogRootsOptions } from "../config/resolveCatalogRoots.js";
|
|
2
3
|
import type { StageflowHostBootstrap } from "./bootstrap.js";
|
|
4
|
+
export type CatalogRootApiRecord = {
|
|
5
|
+
project_root: string;
|
|
6
|
+
kind: CatalogRoot["kind"];
|
|
7
|
+
label: string;
|
|
8
|
+
read_only: boolean;
|
|
9
|
+
available: boolean;
|
|
10
|
+
unavailable_reason?: string;
|
|
11
|
+
};
|
|
12
|
+
export declare function catalogRootLabel(root: CatalogRoot): string;
|
|
13
|
+
export declare function mapCatalogRootForApi(root: CatalogRoot): CatalogRootApiRecord;
|
|
14
|
+
export declare function listCatalogRootsForApi(options: ResolveCatalogRootsOptions): Promise<CatalogRootApiRecord[]>;
|
|
3
15
|
export declare function handleLivez(_req: IncomingMessage, res: ServerResponse): void;
|
|
4
16
|
export declare function handleReadyz(_req: IncomingMessage, res: ServerResponse, boot: StageflowHostBootstrap): Promise<void>;
|
|
5
17
|
export declare function buildRichHealthPayload(boot: StageflowHostBootstrap): Promise<Record<string, unknown>>;
|
|
@@ -1,12 +1,37 @@
|
|
|
1
|
+
import path from "node:path";
|
|
1
2
|
import { getAuthStatus, } from "../agent/providerAuth.js";
|
|
2
3
|
import { PACKAGE_VERSION, BUILD_SHA } from "../package-meta.js";
|
|
3
4
|
import { globalStageflowHome } from "../project/globalHome.js";
|
|
4
5
|
import { redactHostConfig } from "../config/hostConfig.js";
|
|
5
|
-
import { resolveCatalogRoots } from "../config/resolveCatalogRoots.js";
|
|
6
|
+
import { resolveCatalogRoots, } from "../config/resolveCatalogRoots.js";
|
|
6
7
|
import { json } from "./createHttpHost.js";
|
|
7
8
|
import { livezBody, probeGitVersion, readSchemaHealth, runReadyzChecks, } from "../diagnostics/checks.js";
|
|
8
9
|
import { buildEgressHealth } from "../net/proxy.js";
|
|
9
10
|
import { toolchainHealthMap } from "../preflight/toolchain.js";
|
|
11
|
+
export function catalogRootLabel(root) {
|
|
12
|
+
if (root.kind === "workspace")
|
|
13
|
+
return "Workspace";
|
|
14
|
+
if (root.kind === "seeded")
|
|
15
|
+
return "Examples (read-only)";
|
|
16
|
+
const base = path.basename(root.path.replace(/\\/g, "/"));
|
|
17
|
+
return base || root.project_root;
|
|
18
|
+
}
|
|
19
|
+
export function mapCatalogRootForApi(root) {
|
|
20
|
+
return {
|
|
21
|
+
project_root: root.project_root,
|
|
22
|
+
kind: root.kind,
|
|
23
|
+
label: catalogRootLabel(root),
|
|
24
|
+
read_only: root.read_only,
|
|
25
|
+
available: root.available !== false,
|
|
26
|
+
...(root.available === false && root.unavailable_reason
|
|
27
|
+
? { unavailable_reason: root.unavailable_reason }
|
|
28
|
+
: {}),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export async function listCatalogRootsForApi(options) {
|
|
32
|
+
const roots = await resolveCatalogRoots(options);
|
|
33
|
+
return roots.map(mapCatalogRootForApi);
|
|
34
|
+
}
|
|
10
35
|
function bootProvidersSnapshot(providerBoot) {
|
|
11
36
|
return providerBoot
|
|
12
37
|
? {
|
|
@@ -101,11 +126,7 @@ export async function buildRichHealthPayload(boot) {
|
|
|
101
126
|
toolchain: toolchainHealthMap(),
|
|
102
127
|
store_filesystem: boot.storeFilesystem ?? null,
|
|
103
128
|
egress: buildEgressHealth(),
|
|
104
|
-
catalog_roots: catalogRoots.map(
|
|
105
|
-
project_root: r.project_root,
|
|
106
|
-
kind: r.kind,
|
|
107
|
-
read_only: r.read_only,
|
|
108
|
-
})),
|
|
129
|
+
catalog_roots: catalogRoots.map(mapCatalogRootForApi),
|
|
109
130
|
boot_providers,
|
|
110
131
|
providers_live,
|
|
111
132
|
providers: boot_providers,
|
package/dist/server/http.d.ts
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { StagePort } from "../agent/port.js";
|
|
2
2
|
import { type ProviderAuthContext } from "../agent/providerAuth.js";
|
|
3
|
+
import { type LiveViewRoutesOptions } from "./liveViewRoutes.js";
|
|
3
4
|
import { WorkshopChatSessionRegistry } from "../workshop/chatTurn.js";
|
|
4
|
-
import { type
|
|
5
|
+
import { type AgentPort } from "../operatorAgent/index.js";
|
|
5
6
|
import type { RunStoreKind } from "../runstore/createStore.js";
|
|
6
7
|
import type { RunStore } from "../runstore/port.js";
|
|
7
8
|
import type { RunManager } from "../runtime/runManager.js";
|
|
8
9
|
import type { RunChangeBus } from "../runtime/runChangeBus.js";
|
|
10
|
+
import type { StageBrowserSupport } from "../browser/browserHost.js";
|
|
9
11
|
import { EmailTriggers } from "../email/triggers.js";
|
|
10
12
|
import { type AllowedHosts } from "./allowedHosts.js";
|
|
11
13
|
import { type ControlTokens } from "./controlToken.js";
|
|
12
14
|
import { DEFAULT_PORT, type HttpHostEnvelope, type HttpHostRouteContext } from "./createHttpHost.js";
|
|
13
15
|
import { type ShutdownController } from "./shutdown.js";
|
|
14
16
|
export type UiServerOptions = {
|
|
15
|
-
agent:
|
|
17
|
+
agent: StagePort;
|
|
16
18
|
cwd?: string;
|
|
17
19
|
agentDir?: string;
|
|
18
20
|
rootDir?: string;
|
|
@@ -28,8 +30,9 @@ export type UiServerOptions = {
|
|
|
28
30
|
runChangeBus?: RunChangeBus;
|
|
29
31
|
allowedHosts?: AllowedHosts;
|
|
30
32
|
controlTokens?: ControlTokens;
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
browser?: StageBrowserSupport;
|
|
34
|
+
/** Optional AgentPort. Workshop is the caller today; tests inject a fake. */
|
|
35
|
+
workshopOperatorHost?: AgentPort;
|
|
33
36
|
};
|
|
34
37
|
export declare function defaultUiDistDir(): string;
|
|
35
38
|
export type OperatorRouteDeps = {
|
|
@@ -43,14 +46,16 @@ export type OperatorRouteDeps = {
|
|
|
43
46
|
uiDistDir?: string;
|
|
44
47
|
allowedHosts?: AllowedHosts;
|
|
45
48
|
controlTokens?: ControlTokens;
|
|
49
|
+
/** Test seams for live view (fake relay, clock, audit sink); production builds everything from persisted state. */
|
|
50
|
+
liveView?: Omit<LiveViewRoutesOptions, "store" | "controlTokens">;
|
|
46
51
|
/** Live shutdown controller; set after listen so restore can beginDrain. */
|
|
47
52
|
getShutdown?: () => import("./shutdown.js").ShutdownController | undefined;
|
|
48
53
|
/**
|
|
49
|
-
* Optional
|
|
50
|
-
* Distinct from
|
|
51
|
-
*
|
|
54
|
+
* Optional AgentPort (tests inject the fake host).
|
|
55
|
+
* Distinct from StagePort. Defaults to resolveAgentPort (Pi).
|
|
56
|
+
* The fake host remains available via createWorkshopOperatorHost.
|
|
52
57
|
*/
|
|
53
|
-
workshopOperatorHost?:
|
|
58
|
+
workshopOperatorHost?: AgentPort;
|
|
54
59
|
/**
|
|
55
60
|
* Optional durable Workshop chat registry (host sessions keyed by session id).
|
|
56
61
|
* Defaults to a registry owned by this route surface.
|
|
@@ -64,7 +69,11 @@ export type OperatorRouteDeps = {
|
|
|
64
69
|
* `startMcpServer` (headless global-service daemon) — both need the REST
|
|
65
70
|
* API; only the former needs the UI files.
|
|
66
71
|
*/
|
|
67
|
-
export
|
|
72
|
+
export type OperatorRoutes = ((ctx: HttpHostRouteContext) => Promise<boolean | void>) & {
|
|
73
|
+
/** Ends live view streams, credentials and relay sessions. Browsers are not torn down. */
|
|
74
|
+
dispose(): Promise<void>;
|
|
75
|
+
};
|
|
76
|
+
export declare function createOperatorRoutes(deps: OperatorRouteDeps): OperatorRoutes;
|
|
68
77
|
export declare function startUiServer(options: UiServerOptions): Promise<HttpHostEnvelope & {
|
|
69
78
|
shutdown: ShutdownController;
|
|
70
79
|
}>;
|