stageflow 0.25.0 → 0.30.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 +14 -3
- package/builtin-skills/browser/SKILL.md +42 -0
- package/dist/a2a/contracts.d.ts +1 -0
- package/dist/a2a/contracts.js +1 -0
- package/dist/a2a/registry.d.ts +2 -0
- package/dist/a2a/registry.js +20 -1
- package/dist/a2a/server.d.ts +7 -0
- package/dist/a2a/server.js +5 -2
- package/dist/a2a/service.d.ts +1 -1
- package/dist/a2a/service.js +57 -8
- package/dist/a2a/store.d.ts +8 -5
- package/dist/a2a/store.js +24 -67
- package/dist/agent/activity.d.ts +3 -0
- package/dist/agent/bootProviderConfig.d.ts +21 -0
- package/dist/agent/bootProviderConfig.js +74 -0
- package/dist/agent/claudeAdapter.js +2 -2
- package/dist/agent/cursorProvider.d.ts +2 -0
- package/dist/agent/cursorProvider.js +30 -5
- package/dist/agent/fakeAgent.d.ts +1 -0
- package/dist/agent/fakeAgent.js +13 -0
- package/dist/agent/piAdapter.d.ts +11 -24
- package/dist/agent/piAdapter.js +107 -50
- package/dist/agent/piIsolatedMcp.d.ts +2 -0
- package/dist/agent/piIsolatedMcp.js +10 -2
- package/dist/agent/piSessionFactory.d.ts +38 -0
- package/dist/agent/piSessionFactory.js +60 -0
- package/dist/agent/port.d.ts +8 -0
- package/dist/agent/streamLogRedact.d.ts +7 -1
- package/dist/agent/streamLogRedact.js +26 -11
- package/dist/browser/anchor.d.ts +27 -0
- package/dist/browser/anchor.js +127 -0
- package/dist/browser/auditSink.d.ts +38 -0
- package/dist/browser/auditSink.js +34 -0
- package/dist/browser/browserHost.d.ts +86 -0
- package/dist/browser/browserHost.js +7 -0
- package/dist/browser/browserSweep.d.ts +14 -0
- package/dist/browser/browserSweep.js +54 -0
- package/dist/browser/browserTeardown.d.ts +56 -0
- package/dist/browser/browserTeardown.js +235 -0
- package/dist/browser/fakeRemoteBrowserHost.d.ts +2 -0
- package/dist/browser/fakeRemoteBrowserHost.js +34 -0
- package/dist/browser/gateHandoff.d.ts +25 -0
- package/dist/browser/gateHandoff.js +83 -0
- package/dist/browser/humanLogin.d.ts +18 -0
- package/dist/browser/humanLogin.js +34 -0
- package/dist/browser/keyProvider.d.ts +10 -0
- package/dist/browser/keyProvider.js +39 -0
- package/dist/browser/localBrowserHost.d.ts +10 -0
- package/dist/browser/localBrowserHost.js +152 -0
- package/dist/browser/localProfileLock.d.ts +2 -0
- package/dist/browser/localProfileLock.js +218 -0
- package/dist/browser/localProfileStore.d.ts +5 -0
- package/dist/browser/localProfileStore.js +91 -0
- package/dist/browser/loginCheck.d.ts +53 -0
- package/dist/browser/loginCheck.js +147 -0
- package/dist/browser/memoryProfileLock.d.ts +2 -0
- package/dist/browser/memoryProfileLock.js +53 -0
- package/dist/browser/memoryProfileStore.d.ts +2 -0
- package/dist/browser/memoryProfileStore.js +31 -0
- package/dist/browser/navigationAudit.d.ts +16 -0
- package/dist/browser/navigationAudit.js +53 -0
- package/dist/browser/persistedEnv.d.ts +3 -0
- package/dist/browser/persistedEnv.js +15 -0
- package/dist/browser/profileLock.d.ts +40 -0
- package/dist/browser/profileLock.js +10 -0
- package/dist/browser/profileStore.d.ts +23 -0
- package/dist/browser/profileStore.js +39 -0
- package/dist/browser/runLiveness.d.ts +13 -0
- package/dist/browser/runLiveness.js +39 -0
- package/dist/browser/sitePolicy.d.ts +10 -0
- package/dist/browser/sitePolicy.js +61 -0
- package/dist/browser/stageBrowserEnv.d.ts +22 -0
- package/dist/browser/stageBrowserEnv.js +147 -0
- package/dist/browser/stageProfileLock.d.ts +17 -0
- package/dist/browser/stageProfileLock.js +39 -0
- package/dist/cli/artifactCommand.js +9 -16
- package/dist/cli/backupCommand.d.ts +9 -0
- package/dist/cli/backupCommand.js +111 -0
- package/dist/cli/browserCommand.d.ts +44 -0
- package/dist/cli/browserCommand.js +472 -0
- package/dist/cli/debugRunCommand.d.ts +10 -0
- package/dist/cli/debugRunCommand.js +109 -0
- package/dist/cli/doctorCommand.d.ts +32 -0
- package/dist/cli/doctorCommand.js +453 -0
- package/dist/cli/envelopeCommand.js +9 -2
- package/dist/cli/exportAllCommand.d.ts +55 -0
- package/dist/cli/exportAllCommand.js +218 -0
- package/dist/cli/exportRunCommand.js +23 -21
- package/dist/cli/hostClient.d.ts +41 -3
- package/dist/cli/hostClient.js +129 -14
- package/dist/cli/initCommand.d.ts +1 -0
- package/dist/cli/initCommand.js +23 -7
- package/dist/cli/initTemplates.d.ts +5 -2
- package/dist/cli/initTemplates.js +32 -2
- package/dist/cli/resolveSafeOutPath.d.ts +2 -0
- package/dist/cli/resolveSafeOutPath.js +40 -0
- package/dist/cli/restoreCommand.d.ts +10 -0
- package/dist/cli/restoreCommand.js +90 -0
- package/dist/cli/runCommand.d.ts +3 -2
- package/dist/cli/runCommand.js +93 -11
- package/dist/cli/runOutput.d.ts +4 -0
- package/dist/cli/runOutput.js +33 -7
- package/dist/cli/runStageCommand.d.ts +1 -0
- package/dist/cli/runStageCommand.js +44 -25
- package/dist/cli/runsCommand.d.ts +1 -1
- package/dist/cli/runsCommand.js +168 -10
- package/dist/cli/triggerCommand.d.ts +12 -0
- package/dist/cli/triggerCommand.js +183 -0
- package/dist/cli/validateCommand.d.ts +1 -1
- package/dist/cli/validateCommand.js +23 -6
- package/dist/cli.js +202 -32
- package/dist/config/browseCatalog.d.ts +1 -0
- package/dist/config/browseCatalog.js +5 -4
- package/dist/config/builtinSkills.d.ts +4 -0
- package/dist/config/builtinSkills.js +23 -0
- package/dist/config/catalogRelativePath.d.ts +63 -0
- package/dist/config/catalogRelativePath.js +126 -0
- package/dist/config/configOrigin.d.ts +27 -0
- package/dist/config/configOrigin.js +59 -0
- package/dist/config/createTrigger.d.ts +27 -0
- package/dist/config/createTrigger.js +232 -0
- package/dist/config/draftPackage.d.ts +117 -0
- package/dist/config/draftPackage.js +550 -0
- package/dist/config/ensureCatalogScanRoot.d.ts +16 -0
- package/dist/config/ensureCatalogScanRoot.js +73 -0
- package/dist/config/hostConfig.d.ts +57 -0
- package/dist/config/hostConfig.js +360 -0
- package/dist/config/listSkills.d.ts +26 -0
- package/dist/config/listSkills.js +206 -5
- package/dist/config/loadOutcome.d.ts +7 -1
- package/dist/config/loadPipeline.js +39 -2
- package/dist/config/loadStage.js +25 -0
- package/dist/config/loadStageflowManifest.js +25 -0
- package/dist/config/loadTask.d.ts +2 -0
- package/dist/config/loadTask.js +57 -18
- package/dist/config/loadTrigger.d.ts +9 -0
- package/dist/config/loadTrigger.js +120 -0
- package/dist/config/materializeStageModels.js +5 -1
- package/dist/config/mergePipelineIncludes.d.ts +3 -0
- package/dist/config/mergePipelineIncludes.js +19 -0
- package/dist/config/migrateYaml.js +6 -11
- package/dist/config/multiProjectCatalog.d.ts +32 -0
- package/dist/config/multiProjectCatalog.js +150 -0
- package/dist/config/normalizePipelineStageEntry.js +27 -1
- package/dist/config/parseCompletionContract.js +6 -0
- package/dist/config/pipelineStageKeys.js +3 -0
- package/dist/config/publishDraftPackage.d.ts +7 -0
- package/dist/config/publishDraftPackage.js +25 -0
- package/dist/config/resolveCatalogContext.js +1 -1
- package/dist/config/resolveCatalogRoots.d.ts +27 -0
- package/dist/config/resolveCatalogRoots.js +76 -0
- package/dist/config/resolveModel.d.ts +7 -1
- package/dist/config/resolveModel.js +11 -1
- package/dist/config/resolvePipelineDag.js +1 -1
- package/dist/config/resolveStageMcpServers.d.ts +9 -1
- package/dist/config/resolveStageMcpServers.js +36 -9
- package/dist/config/scanCatalogPaths.d.ts +1 -1
- package/dist/config/scanCatalogPaths.js +6 -2
- package/dist/config/secretFromEnvOrFile.d.ts +9 -0
- package/dist/config/secretFromEnvOrFile.js +34 -0
- package/dist/config/seededCatalog.d.ts +11 -0
- package/dist/config/seededCatalog.js +29 -0
- package/dist/config/stageBrowser.d.ts +12 -0
- package/dist/config/stageBrowser.js +118 -0
- package/dist/config/toolRequires.d.ts +24 -0
- package/dist/config/toolRequires.js +115 -0
- package/dist/config/triggerCatalog.d.ts +10 -0
- package/dist/config/triggerCatalog.js +37 -0
- package/dist/config/validateCatalog.d.ts +17 -3
- package/dist/config/validateCatalog.js +223 -3
- package/dist/config/validateCompletionContract.js +8 -0
- package/dist/diagnostics/checks.d.ts +39 -0
- package/dist/diagnostics/checks.js +135 -0
- package/dist/envelope/preEmitChecks.d.ts +1 -1
- package/dist/envelope/preEmitChecks.js +8 -0
- package/dist/errors/codes.d.ts +14 -0
- package/dist/errors/codes.js +59 -0
- package/dist/git/cache.d.ts +14 -0
- package/dist/git/cache.js +150 -0
- package/dist/git/credentials.d.ts +9 -0
- package/dist/git/credentials.js +88 -0
- package/dist/git/errors.d.ts +20 -0
- package/dist/git/errors.js +94 -0
- package/dist/git/exec.d.ts +16 -0
- package/dist/git/exec.js +135 -0
- package/dist/git/operations.d.ts +29 -0
- package/dist/git/operations.js +153 -0
- package/dist/git/version.d.ts +1 -0
- package/dist/git/version.js +10 -0
- package/dist/logging/audit.d.ts +16 -0
- package/dist/logging/audit.js +19 -0
- package/dist/logging/commonWords.d.ts +2 -0
- package/dist/logging/commonWords.js +13 -0
- package/dist/logging/logger.d.ts +49 -0
- package/dist/logging/logger.js +193 -0
- package/dist/logging/namedSecrets.d.ts +6 -0
- package/dist/logging/namedSecrets.js +58 -0
- package/dist/logging/redact.d.ts +17 -0
- package/dist/logging/redact.js +105 -0
- package/dist/mcp/catalogTools.js +492 -81
- package/dist/mcp/checkoutTools.d.ts +52 -0
- package/dist/mcp/checkoutTools.js +332 -0
- package/dist/mcp/controlTools.js +182 -6
- package/dist/mcp/deps.d.ts +3 -0
- package/dist/mcp/getStartedTool.d.ts +3 -0
- package/dist/mcp/getStartedTool.js +62 -0
- package/dist/mcp/readArtifact.d.ts +11 -0
- package/dist/mcp/readArtifact.js +46 -30
- package/dist/mcp/server.js +2 -0
- package/dist/mcp/tools.js +6 -0
- package/dist/mcp/triggerTools.d.ts +3 -0
- package/dist/mcp/triggerTools.js +176 -0
- package/dist/net/proxy.d.ts +14 -0
- package/dist/net/proxy.js +78 -0
- package/dist/operatorAgent/docsRetrieval.d.ts +40 -0
- package/dist/operatorAgent/docsRetrieval.js +269 -0
- package/dist/operatorAgent/draftContext.d.ts +16 -0
- package/dist/operatorAgent/draftContext.js +68 -0
- package/dist/operatorAgent/fakeHost.d.ts +39 -0
- package/dist/operatorAgent/fakeHost.js +92 -0
- package/dist/operatorAgent/host.d.ts +40 -0
- package/dist/operatorAgent/host.js +179 -0
- package/dist/operatorAgent/index.d.ts +9 -0
- package/dist/operatorAgent/index.js +8 -0
- package/dist/operatorAgent/piModel.d.ts +80 -0
- package/dist/operatorAgent/piModel.js +528 -0
- package/dist/operatorAgent/profiles/workshopAuthor.d.ts +23 -0
- package/dist/operatorAgent/profiles/workshopAuthor.js +338 -0
- package/dist/operatorAgent/profiles/workshopAuthorPlaybook.d.ts +6 -0
- package/dist/operatorAgent/profiles/workshopAuthorPlaybook.js +103 -0
- package/dist/operatorAgent/profiles/workshopAuthorTools.d.ts +57 -0
- package/dist/operatorAgent/profiles/workshopAuthorTools.js +623 -0
- package/dist/operatorAgent/proposals.d.ts +32 -0
- package/dist/operatorAgent/proposals.js +144 -0
- package/dist/operatorAgent/types.d.ts +128 -0
- package/dist/operatorAgent/types.js +1 -0
- package/dist/package-meta.d.ts +2 -1
- package/dist/package-meta.js +2 -1
- package/dist/preflight/bash.d.ts +8 -0
- package/dist/preflight/bash.js +34 -0
- package/dist/preflight/claudeRoot.d.ts +11 -0
- package/dist/preflight/claudeRoot.js +23 -0
- package/dist/preflight/mcpCommands.d.ts +8 -0
- package/dist/preflight/mcpCommands.js +36 -0
- package/dist/preflight/pipelinePreflight.d.ts +40 -0
- package/dist/preflight/pipelinePreflight.js +192 -0
- package/dist/preflight/tls.d.ts +6 -0
- package/dist/preflight/tls.js +18 -0
- package/dist/preflight/toolchain.d.ts +45 -0
- package/dist/preflight/toolchain.js +219 -0
- package/dist/project/findManifestRoot.d.ts +3 -0
- package/dist/project/findManifestRoot.js +35 -0
- package/dist/project/findProjectRoot.js +3 -4
- package/dist/project/globalHome.d.ts +7 -0
- package/dist/project/globalHome.js +63 -2
- package/dist/project/resolveProjectContext.js +2 -2
- package/dist/project/resolveStageflowContext.d.ts +7 -0
- package/dist/project/resolveStageflowContext.js +46 -30
- package/dist/projection/projectRun.d.ts +2 -1
- package/dist/projection/projectRun.js +1 -0
- package/dist/runstore/assertTmpdir.d.ts +1 -0
- package/dist/runstore/assertTmpdir.js +25 -0
- package/dist/runstore/backup.d.ts +52 -0
- package/dist/runstore/backup.js +292 -0
- package/dist/runstore/createStore.d.ts +18 -1
- package/dist/runstore/createStore.js +64 -5
- package/dist/runstore/debugBundle.d.ts +60 -0
- package/dist/runstore/debugBundle.js +143 -0
- package/dist/runstore/diskUsage.d.ts +50 -0
- package/dist/runstore/diskUsage.js +214 -0
- package/dist/runstore/exportRunPayload.d.ts +8 -0
- package/dist/runstore/exportRunPayload.js +23 -0
- package/dist/runstore/normalizeCatalogPath.d.ts +1 -0
- package/dist/runstore/normalizeCatalogPath.js +10 -0
- package/dist/runstore/paths.d.ts +5 -0
- package/dist/runstore/paths.js +145 -1
- package/dist/runstore/port.d.ts +139 -13
- package/dist/runstore/port.js +8 -1
- package/dist/runstore/restore.d.ts +81 -0
- package/dist/runstore/restore.js +355 -0
- package/dist/runstore/retention.d.ts +27 -0
- package/dist/runstore/retention.js +74 -0
- package/dist/runstore/runManifest.d.ts +146 -0
- package/dist/runstore/runManifest.js +288 -0
- package/dist/runstore/runProjection.d.ts +3 -1
- package/dist/runstore/runProjection.js +63 -1
- package/dist/runstore/sqlite/SqliteRunStore.d.ts +35 -3
- package/dist/runstore/sqlite/SqliteRunStore.js +442 -219
- package/dist/runstore/sqlite/applyStorePragmas.d.ts +39 -0
- package/dist/runstore/sqlite/applyStorePragmas.js +145 -0
- package/dist/runstore/sqlite/migrations/001-baseline.d.ts +7 -0
- package/dist/runstore/sqlite/migrations/001-baseline.js +10 -0
- package/dist/runstore/sqlite/migrations/002-repository-binding.d.ts +7 -0
- package/dist/runstore/sqlite/migrations/002-repository-binding.js +29 -0
- package/dist/runstore/sqlite/migrations/003-run-lifecycle.d.ts +7 -0
- package/dist/runstore/sqlite/migrations/003-run-lifecycle.js +28 -0
- package/dist/runstore/sqlite/migrations/004-auto-resume-count.d.ts +7 -0
- package/dist/runstore/sqlite/migrations/004-auto-resume-count.js +19 -0
- package/dist/runstore/sqlite/migrations/005-config-origins.d.ts +7 -0
- package/dist/runstore/sqlite/migrations/005-config-origins.js +19 -0
- package/dist/runstore/sqlite/migrations/006-pipeline-body-and-caller.d.ts +7 -0
- package/dist/runstore/sqlite/migrations/006-pipeline-body-and-caller.js +28 -0
- package/dist/runstore/sqlite/migrations/007-projects-registry.d.ts +7 -0
- package/dist/runstore/sqlite/migrations/007-projects-registry.js +31 -0
- package/dist/runstore/sqlite/migrations/008-triggers-table.d.ts +7 -0
- package/dist/runstore/sqlite/migrations/008-triggers-table.js +19 -0
- package/dist/runstore/sqlite/migrations/009-trigger-next-run.d.ts +7 -0
- package/dist/runstore/sqlite/migrations/009-trigger-next-run.js +19 -0
- package/dist/runstore/sqlite/migrations/010-trigger-adapter-state.d.ts +7 -0
- package/dist/runstore/sqlite/migrations/010-trigger-adapter-state.js +17 -0
- package/dist/runstore/sqlite/migrations/index.d.ts +21 -0
- package/dist/runstore/sqlite/migrations/index.js +78 -0
- package/dist/runstore/sqlite/schema.d.ts +20 -1
- package/dist/runstore/sqlite/schema.js +277 -1
- package/dist/runstore/sqlite/storeOpenError.d.ts +6 -0
- package/dist/runstore/sqlite/storeOpenError.js +11 -0
- package/dist/runstore/sqlite/storeSchemaError.d.ts +5 -0
- package/dist/runstore/sqlite/storeSchemaError.js +8 -0
- package/dist/runstore/stageExecution.js +3 -0
- package/dist/runstore/storeFilesystem.d.ts +32 -0
- package/dist/runstore/storeFilesystem.js +148 -0
- package/dist/runstore/trackProjection.js +2 -0
- package/dist/runstore/workspaceLayout.d.ts +13 -0
- package/dist/runstore/workspaceLayout.js +76 -0
- package/dist/runtime/answerResume.d.ts +1 -0
- package/dist/runtime/answerResume.js +3 -1
- package/dist/runtime/completionCheckRunner.d.ts +15 -1
- package/dist/runtime/completionCheckRunner.js +67 -7
- package/dist/runtime/containerLimits.d.ts +16 -0
- package/dist/runtime/containerLimits.js +84 -0
- package/dist/runtime/credentialBinding.d.ts +2 -0
- package/dist/runtime/credentialBinding.js +3 -0
- package/dist/runtime/credentialMaterialisation.d.ts +28 -0
- package/dist/runtime/credentialMaterialisation.js +128 -0
- package/dist/runtime/emailSource.d.ts +72 -0
- package/dist/runtime/emailSource.js +304 -0
- package/dist/runtime/gitCheckoutCapability.js +7 -13
- package/dist/runtime/githubPollSource.d.ts +86 -0
- package/dist/runtime/githubPollSource.js +284 -0
- package/dist/runtime/pipelineRunner.d.ts +40 -1
- package/dist/runtime/pipelineRunner.js +181 -17
- package/dist/runtime/pipelineScheduler.d.ts +17 -0
- package/dist/runtime/pipelineScheduler.js +220 -28
- package/dist/runtime/reloadRunCatalog.js +6 -1
- package/dist/runtime/repositoryMaterialize.d.ts +47 -0
- package/dist/runtime/repositoryMaterialize.js +235 -0
- package/dist/runtime/resumeTimedOut.d.ts +1 -1
- package/dist/runtime/resumeTimedOut.js +5 -2
- package/dist/runtime/runChangeBus.js +9 -0
- package/dist/runtime/runDeletion.d.ts +7 -0
- package/dist/runtime/runDeletion.js +37 -0
- package/dist/runtime/runManager.d.ts +169 -4
- package/dist/runtime/runManager.js +1748 -83
- package/dist/runtime/runRetentionSweep.d.ts +31 -0
- package/dist/runtime/runRetentionSweep.js +328 -0
- package/dist/runtime/runRetryCoordinator.d.ts +4 -0
- package/dist/runtime/runRetryCoordinator.js +20 -2
- package/dist/runtime/runSkills.d.ts +40 -0
- package/dist/runtime/runSkills.js +173 -0
- package/dist/runtime/scheduleSource.d.ts +38 -0
- package/dist/runtime/scheduleSource.js +119 -0
- package/dist/runtime/settingsFile.d.ts +5 -0
- package/dist/runtime/settingsFile.js +61 -54
- package/dist/runtime/stageAttemptBootstrap.d.ts +5 -1
- package/dist/runtime/stageAttemptBootstrap.js +250 -27
- package/dist/runtime/stageCacheEnv.d.ts +6 -0
- package/dist/runtime/stageCacheEnv.js +34 -0
- package/dist/runtime/stageConcurrency.d.ts +2 -1
- package/dist/runtime/stageConcurrency.js +4 -2
- package/dist/runtime/stageEnvironment.d.ts +38 -0
- package/dist/runtime/stageEnvironment.js +194 -0
- package/dist/runtime/stageHitl.d.ts +1 -0
- package/dist/runtime/stageHitl.js +5 -1
- package/dist/runtime/stageProcessLauncher.d.ts +20 -0
- package/dist/runtime/stageProcessLauncher.js +236 -41
- package/dist/runtime/stageRecovery.d.ts +3 -1
- package/dist/runtime/stageRecovery.js +19 -4
- package/dist/runtime/stageRoots.d.ts +38 -1
- package/dist/runtime/stageRoots.js +118 -0
- package/dist/runtime/stageRunner.d.ts +6 -0
- package/dist/runtime/stageRunner.js +32 -6
- package/dist/runtime/stageSecretDecl.d.ts +9 -0
- package/dist/runtime/stageSecretDecl.js +102 -0
- package/dist/runtime/stageSecrets.d.ts +40 -0
- package/dist/runtime/stageSecrets.js +181 -0
- package/dist/runtime/stageStreamLog.d.ts +1 -0
- package/dist/runtime/stageStreamLog.js +2 -1
- package/dist/runtime/stageWorker.d.ts +3 -2
- package/dist/runtime/stageWorker.js +58 -10
- package/dist/runtime/stageWorkerProtocol.d.ts +5 -0
- package/dist/runtime/stageWorkerProtocol.js +8 -0
- package/dist/runtime/startPayload.d.ts +32 -0
- package/dist/runtime/startPayload.js +59 -0
- package/dist/runtime/taskInput.js +14 -5
- package/dist/runtime/triggerCatalog.d.ts +6 -0
- package/dist/runtime/triggerCatalog.js +24 -0
- package/dist/runtime/triggerEventMatch.d.ts +2 -0
- package/dist/runtime/triggerEventMatch.js +6 -0
- package/dist/runtime/triggerPort.d.ts +14 -0
- package/dist/runtime/triggerPort.js +1 -0
- package/dist/runtime/triggerRunner.d.ts +17 -0
- package/dist/runtime/triggerRunner.js +89 -0
- package/dist/runtime/verifiedStageExecution.d.ts +8 -0
- package/dist/runtime/verifiedStageExecution.js +16 -1
- package/dist/runtime/webhookSignature.d.ts +1 -0
- package/dist/runtime/webhookSignature.js +12 -0
- package/dist/runtime/workspaceBinding.d.ts +20 -0
- package/dist/runtime/workspaceBinding.js +60 -0
- package/dist/server/allowedHosts.d.ts +19 -0
- package/dist/server/allowedHosts.js +179 -0
- package/dist/server/bootstrap.d.ts +42 -2
- package/dist/server/bootstrap.js +273 -5
- package/dist/server/controlToken.d.ts +47 -0
- package/dist/server/controlToken.js +254 -0
- package/dist/server/createHttpHost.d.ts +11 -2
- package/dist/server/createHttpHost.js +106 -10
- package/dist/server/ensureGlobalService.d.ts +5 -1
- package/dist/server/ensureGlobalService.js +35 -1
- package/dist/server/healthSurfaces.d.ts +6 -0
- package/dist/server/healthSurfaces.js +123 -0
- package/dist/server/http.d.ts +27 -1
- package/dist/server/http.js +2254 -477
- package/dist/server/listenHost.d.ts +5 -0
- package/dist/server/listenHost.js +56 -0
- package/dist/server/mcpHost.d.ts +10 -1
- package/dist/server/mcpHost.js +36 -6
- package/dist/server/operatorResults.d.ts +2 -2
- package/dist/server/operatorResults.js +40 -29
- package/dist/server/requestAuthContext.d.ts +12 -0
- package/dist/server/requestAuthContext.js +21 -0
- package/dist/server/shutdown.d.ts +69 -0
- package/dist/server/shutdown.js +219 -0
- package/dist/server/triggerRoutes.d.ts +15 -0
- package/dist/server/triggerRoutes.js +268 -0
- package/dist/tools/askOperator.d.ts +3 -2
- package/dist/types/completion.d.ts +3 -0
- package/dist/types/pipeline.d.ts +10 -1
- package/dist/types/preEmitCheck.d.ts +7 -0
- package/dist/types/stage.d.ts +22 -0
- package/dist/types/stageflowManifest.d.ts +3 -0
- package/dist/types/task.d.ts +8 -0
- package/dist/types/trigger.d.ts +18 -0
- package/dist/types/trigger.js +1 -0
- package/dist/ui/assets/{index-CSsDued1.css → index-Bv4p1aPK.css} +1 -1
- package/dist/ui/assets/index-CntB4bZR.js +133 -0
- package/dist/ui/index.html +2 -2
- package/dist/workshop/autosave.d.ts +58 -0
- package/dist/workshop/autosave.js +222 -0
- package/dist/workshop/buildStore.d.ts +79 -0
- package/dist/workshop/buildStore.js +326 -0
- package/dist/workshop/chatTurn.d.ts +232 -0
- package/dist/workshop/chatTurn.js +475 -0
- package/dist/workshop/modelSettings.d.ts +18 -0
- package/dist/workshop/modelSettings.js +44 -0
- package/dist/workshop/sessionStore.d.ts +61 -0
- package/dist/workshop/sessionStore.js +254 -0
- package/dist/workshop/workshopPin.d.ts +72 -0
- package/dist/workshop/workshopPin.js +193 -0
- package/examples/README.md +99 -0
- package/examples/archify-on-pr/README.md +213 -0
- package/examples/archify-on-pr/archify-on-pr.pipeline.yaml +19 -0
- package/examples/archify-on-pr/archify-on-pr.task.yaml +19 -0
- package/examples/archify-on-pr/author-diagrams.yaml +106 -0
- package/examples/archify-on-pr/detect-changes.yaml +89 -0
- package/examples/browser-session/README.md +77 -0
- package/examples/browser-session/browser-session.pipeline.yaml +50 -0
- package/examples/browser-session/browser-session.task.yaml +6 -0
- package/examples/browser-session/check-login.yaml +22 -0
- package/examples/browser-session/fixture-server.mjs +64 -0
- package/examples/browser-session/human-login.yaml +31 -0
- package/examples/browser-session/merge.yaml +36 -0
- package/examples/browser-session/work-a.yaml +41 -0
- package/examples/browser-session/work-b.yaml +41 -0
- package/examples/ci-validate/README.md +35 -0
- package/examples/ci-validate/check.yaml +13 -0
- package/examples/ci-validate/ci-demo.pipeline.yaml +4 -0
- package/examples/ci-validate/validate.sh +5 -0
- package/examples/compliance-review-demo/README.md +125 -0
- package/examples/compliance-review-demo/compliance-review-demo.pipeline.yaml +29 -0
- package/examples/compliance-review-demo/connect-account.yaml +47 -0
- package/examples/compliance-review-demo/map-to-control.yaml +123 -0
- package/examples/compliance-review-demo/poll-bucket-config.yaml +103 -0
- package/examples/compliance-review-demo/publish-report.yaml +79 -0
- package/examples/compliance-review-demo/review-verdict.yaml +122 -0
- package/examples/compliance-review-demo/run-compliance-check.yaml +96 -0
- package/examples/compliance-review-demo/store-evidence.yaml +143 -0
- package/examples/conditional-fork/README.md +89 -0
- package/examples/conditional-fork/branch-a.yaml +13 -0
- package/examples/conditional-fork/branch-b.yaml +13 -0
- package/examples/conditional-fork/decide.yaml +35 -0
- package/examples/conditional-fork/fork-demo.pipeline.yaml +20 -0
- package/examples/conditional-fork/fork-demo.task.yaml +8 -0
- package/examples/context7-mcp/README.md +42 -0
- package/examples/context7-mcp/context7-mcp.pipeline.yaml +15 -0
- package/examples/context7-mcp/context7-mcp.task.yaml +4 -0
- package/examples/context7-mcp/fetch-docs.yaml +52 -0
- package/examples/context7-mcp/resolve-library.yaml +31 -0
- package/examples/context7-mcp/write-brief.yaml +52 -0
- package/examples/feature-loop/README.md +104 -0
- package/examples/feature-loop/address-feedback.yaml +148 -0
- package/examples/feature-loop/align.yaml +116 -0
- package/examples/feature-loop/decompose.yaml +86 -0
- package/examples/feature-loop/default-model-hierarchy.task.yaml +58 -0
- package/examples/feature-loop/feature-loop.pipeline.yaml +140 -0
- package/examples/feature-loop/feature-loop.task.yaml +25 -0
- package/examples/feature-loop/implement.yaml +128 -0
- package/examples/feature-loop/plan.yaml +111 -0
- package/examples/feature-loop/publish.yaml +167 -0
- package/examples/feature-loop/review.yaml +146 -0
- package/examples/feature-loop/verify.yaml +106 -0
- package/examples/feedback-loop/README.md +72 -0
- package/examples/feedback-loop/VERIFY.md +208 -0
- package/examples/feedback-loop/continue-only.task.yaml +4 -0
- package/examples/feedback-loop/exhaust-require-continue.task.yaml +6 -0
- package/examples/feedback-loop/exhaust-wait-human.task.yaml +11 -0
- package/examples/feedback-loop/feedback-loop-wait-human.pipeline.yaml +23 -0
- package/examples/feedback-loop/feedback-loop.pipeline.yaml +23 -0
- package/examples/feedback-loop/feedback-loop.task.yaml +4 -0
- package/examples/feedback-loop/implement.yaml +14 -0
- package/examples/feedback-loop/plan.yaml +14 -0
- package/examples/feedback-loop/review.yaml +15 -0
- package/examples/feedback-loop/send-back-once.task.yaml +6 -0
- package/examples/feedback-loop/submit.yaml +12 -0
- package/examples/generic-fan-in/README.md +151 -0
- package/examples/generic-fan-in/clarify.yaml +18 -0
- package/examples/generic-fan-in/generic-fan-in-accepted.pipeline.yaml +19 -0
- package/examples/generic-fan-in/generic-fan-in-accepted.task.yaml +8 -0
- package/examples/generic-fan-in/generic-fan-in.pipeline.yaml +18 -0
- package/examples/generic-fan-in/generic-fan-in.task.yaml +9 -0
- package/examples/generic-fan-in/research.yaml +45 -0
- package/examples/generic-fan-in/synthesize.yaml +66 -0
- package/examples/generic-fan-in/validation.yaml +45 -0
- package/examples/github-release/README.md +78 -0
- package/examples/github-release/draft-release-notes.yaml +64 -0
- package/examples/github-release/github-release.pipeline.yaml +11 -0
- package/examples/github-release/github-release.task.yaml +13 -0
- package/examples/github-release/publish-github-release.yaml +64 -0
- package/examples/hello-world/README.md +28 -0
- package/examples/hello-world/hello.pipeline.yaml +4 -0
- package/examples/hello-world/my-task.task.yaml +6 -0
- package/examples/hello-world/research.yaml +18 -0
- package/examples/mcp-hitl-tour/README.md +113 -0
- package/examples/mcp-hitl-tour/draft-angle.yaml +33 -0
- package/examples/mcp-hitl-tour/draft-short.yaml +32 -0
- package/examples/mcp-hitl-tour/emit-angles.yaml +45 -0
- package/examples/mcp-hitl-tour/gather.yaml +31 -0
- package/examples/mcp-hitl-tour/intake.yaml +62 -0
- package/examples/mcp-hitl-tour/mcp-hitl-tour-exhaust.task.yaml +13 -0
- package/examples/mcp-hitl-tour/mcp-hitl-tour.pipeline.yaml +54 -0
- package/examples/mcp-hitl-tour/mcp-hitl-tour.task.yaml +16 -0
- package/examples/mcp-hitl-tour/polish.yaml +33 -0
- package/examples/mcp-hitl-tour/review.yaml +17 -0
- package/examples/mcp-hitl-tour/ship.yaml +25 -0
- package/examples/oss-issue-contribution/README.md +218 -0
- package/examples/oss-issue-contribution/oss-address-review-feedback.yaml +117 -0
- package/examples/oss-issue-contribution/oss-approve-contribution.yaml +181 -0
- package/examples/oss-issue-contribution/oss-approve-plan.yaml +111 -0
- package/examples/oss-issue-contribution/oss-explain-fix.yaml +108 -0
- package/examples/oss-issue-contribution/oss-explain-issue.yaml +114 -0
- package/examples/oss-issue-contribution/oss-implement-source-fix.yaml +171 -0
- package/examples/oss-issue-contribution/oss-investigate-area.yaml +116 -0
- package/examples/oss-issue-contribution/oss-issue-contribution.pipeline.yaml +125 -0
- package/examples/oss-issue-contribution/oss-issue-intake.yaml +106 -0
- package/examples/oss-issue-contribution/oss-plan-investigation.yaml +112 -0
- package/examples/oss-issue-contribution/oss-plan-review.yaml +109 -0
- package/examples/oss-issue-contribution/oss-reproduce-issue.yaml +140 -0
- package/examples/oss-issue-contribution/oss-review-change.yaml +107 -0
- package/examples/oss-issue-contribution/oss-verify-fix.yaml +130 -0
- package/examples/oss-issue-contribution/oss-write-regression-test.yaml +135 -0
- package/examples/oss-issue-contribution/pi-7629.task.yaml +79 -0
- package/examples/oss-issue-contribution/pi-8919.task.yaml +75 -0
- package/examples/oss-issue-contribution/pydantic-ai-7971.task.yaml +53 -0
- package/examples/oss-quick-fix/README.md +65 -0
- package/examples/oss-quick-fix/implement-fix.yaml +84 -0
- package/examples/oss-quick-fix/oss-quick-fix.pipeline.yaml +35 -0
- package/examples/oss-quick-fix/oss-quick-fix.task.yaml +19 -0
- package/examples/oss-quick-fix/ship-fix.yaml +81 -0
- package/examples/oss-quick-fix/understand-issue.yaml +67 -0
- package/examples/oss-quick-fix/verify-fix.yaml +73 -0
- package/examples/plan-review/README.md +37 -0
- package/examples/plan-review/plan-review-followup.yaml +13 -0
- package/examples/plan-review/plan-review.pipeline.yaml +9 -0
- package/examples/plan-review/plan-review.task.yaml +9 -0
- package/examples/plan-review/plan-review.yaml +25 -0
- package/examples/playwright-mcp/README.md +39 -0
- package/examples/playwright-mcp/playwright-mcp.pipeline.yaml +5 -0
- package/examples/playwright-mcp/playwright-mcp.task.yaml +4 -0
- package/examples/playwright-mcp/screenshot.yaml +40 -0
- package/examples/retry-tour/README.md +75 -0
- package/examples/retry-tour/retry-tour.pipeline.yaml +122 -0
- package/examples/retry-tour/retry-tour.task.yaml +9 -0
- package/examples/route-if-tour/README.md +202 -0
- package/examples/route-if-tour/route-if-tour.pipeline.yaml +950 -0
- package/examples/route-if-tour/route-if-tour.task.yaml +4 -0
- package/examples/route-wiring-smoke-test/01-core-routing.pipeline.yaml +168 -0
- package/examples/route-wiring-smoke-test/02-on-gating.pipeline.yaml +44 -0
- package/examples/route-wiring-smoke-test/03-two-entry-points.pipeline.yaml +28 -0
- package/examples/route-wiring-smoke-test/04-entry-false-equivalent-to-omitted.pipeline.yaml +27 -0
- package/examples/route-wiring-smoke-test/05-fork-choice.pipeline.yaml +110 -0
- package/examples/route-wiring-smoke-test/06-fan-out-fan-in.pipeline.yaml +82 -0
- package/examples/route-wiring-smoke-test/07-loop-human-decision.pipeline.yaml +82 -0
- package/examples/route-wiring-smoke-test/08-skip-fallback-and-multi-on-gate.pipeline.yaml +77 -0
- package/examples/route-wiring-smoke-test/09-multi-loop-targets.pipeline.yaml +102 -0
- package/examples/route-wiring-smoke-test/10-uses-dialect-fork.pipeline.yaml +23 -0
- package/examples/route-wiring-smoke-test/11-sequential-io-handoff.pipeline.yaml +37 -0
- package/examples/route-wiring-smoke-test/12-complex-io-schemas.pipeline.yaml +138 -0
- package/examples/route-wiring-smoke-test/13-ref-io-handoff.pipeline.yaml +84 -0
- package/examples/route-wiring-smoke-test/14-if-eq-gating.pipeline.yaml +50 -0
- package/examples/route-wiring-smoke-test/15-if-all-gated.pipeline.yaml +37 -0
- package/examples/route-wiring-smoke-test/16-if-composition.pipeline.yaml +65 -0
- package/examples/route-wiring-smoke-test/17-if-join.pipeline.yaml +80 -0
- package/examples/route-wiring-smoke-test/README.md +377 -0
- package/examples/route-wiring-smoke-test/rejected/01-reject-legacy-needs.pipeline.yaml +26 -0
- package/examples/route-wiring-smoke-test/rejected/02-reject-legacy-fork.pipeline.yaml +25 -0
- package/examples/route-wiring-smoke-test/rejected/03-reject-legacy-feedback-loop.pipeline.yaml +30 -0
- package/examples/route-wiring-smoke-test/rejected/04-reject-missing-entry.pipeline.yaml +24 -0
- package/examples/route-wiring-smoke-test/rejected/05-reject-unreachable.pipeline.yaml +35 -0
- package/examples/route-wiring-smoke-test/rejected/06-reject-allow-none-without-route-select.pipeline.yaml +37 -0
- package/examples/route-wiring-smoke-test/rejected/07-reject-cycle.pipeline.yaml +27 -0
- package/examples/route-wiring-smoke-test/rejected/08-reject-loop-non-ancestor.pipeline.yaml +42 -0
- package/examples/route-wiring-smoke-test/rejected/09-reject-route-select-leaf.pipeline.yaml +26 -0
- package/examples/route-wiring-smoke-test/rejected/12-reject-loop-replay-unsafe.pipeline.yaml +55 -0
- package/examples/route-wiring-smoke-test/rejected/13-reject-multiple-loop-entries.pipeline.yaml +51 -0
- package/examples/route-wiring-smoke-test/rejected/14-reject-duplicate-stage-id.pipeline.yaml +35 -0
- package/examples/route-wiring-smoke-test/rejected/15-reject-unknown-route-target.pipeline.yaml +15 -0
- package/examples/route-wiring-smoke-test/rejected/16-reject-malformed-route-item.pipeline.yaml +15 -0
- package/examples/route-wiring-smoke-test/rejected/17-reject-io-incompatible.pipeline.yaml +33 -0
- package/examples/route-wiring-smoke-test/rejected/18-reject-nested-io.pipeline.yaml +51 -0
- package/examples/route-wiring-smoke-test/rejected/19-reject-array-item-io.pipeline.yaml +55 -0
- package/examples/route-wiring-smoke-test/rejected/20-reject-closed-io.pipeline.yaml +36 -0
- package/examples/route-wiring-smoke-test/rejected/21-reject-ref-io.pipeline.yaml +42 -0
- package/examples/route-wiring-smoke-test/rejected/22-reject-if-unknown-field.pipeline.yaml +33 -0
- package/examples/route-wiring-smoke-test/rejected/23-reject-if-optional-field.pipeline.yaml +32 -0
- package/examples/route-wiring-smoke-test/rejected/24-reject-if-empty-all.pipeline.yaml +31 -0
- package/examples/route-wiring-smoke-test/rejected/25-reject-if-gt-on-string.pipeline.yaml +33 -0
- package/examples/route-wiring-smoke-test/rejected/26-reject-if-optional-nested.pipeline.yaml +36 -0
- package/examples/route-wiring-smoke-test/rejected/27-reject-if-on-loop.pipeline.yaml +63 -0
- package/examples/route-wiring-smoke-test/rejected/29-reject-if-on-failed.pipeline.yaml +46 -0
- package/examples/route-wiring-smoke-test/smoke-test.task.yaml +4 -0
- package/examples/route-wiring-smoke-test/stages/branch-a.yaml +12 -0
- package/examples/route-wiring-smoke-test/stages/branch-b.yaml +12 -0
- package/examples/route-wiring-smoke-test/stages/decide.yaml +12 -0
- package/examples/route-wiring-smoke-test/stages/finish.yaml +12 -0
- package/examples/ship-feature/README.md +190 -0
- package/examples/ship-feature/feat-address-feedback.yaml +119 -0
- package/examples/ship-feature/feat-implement.yaml +180 -0
- package/examples/ship-feature/feat-plan.yaml +120 -0
- package/examples/ship-feature/feat-review.yaml +109 -0
- package/examples/ship-feature/feat-ship.yaml +203 -0
- package/examples/ship-feature/ship-feature.pipeline.yaml +44 -0
- package/examples/ship-feature/ship-feature.task.yaml +78 -0
- package/examples/stage-mcp/README.md +145 -0
- package/examples/stage-mcp/echo-mcp.mjs +20 -0
- package/examples/stage-mcp/stage-mcp-dead.pipeline.yaml +5 -0
- package/examples/stage-mcp/stage-mcp-dead.task.yaml +3 -0
- package/examples/stage-mcp/stage-mcp-missing-var.pipeline.yaml +5 -0
- package/examples/stage-mcp/stage-mcp-missing-var.task.yaml +3 -0
- package/examples/stage-mcp/stage-mcp.pipeline.yaml +5 -0
- package/examples/stage-mcp/stage-mcp.task.yaml +4 -0
- package/examples/stage-mcp/use-echo.yaml +20 -0
- package/examples/stageflow.yaml +51 -0
- package/examples/verify-tour/README.md +80 -0
- package/examples/verify-tour/verify-tour.pipeline.yaml +162 -0
- package/examples/verify-tour/verify-tour.task.yaml +11 -0
- package/package.json +9 -1
- package/skills/stageflow/SKILL.md +6 -6
- package/skills/stageflow/references/control-surface.md +13 -5
- package/skills/stageflow/scripts/detect-host.mjs +14 -1
- package/skills/stageflow/scripts/detect-host.test.mjs +29 -1
- package/skills/stageflow-author/SKILL.md +4 -3
- package/skills/stageflow-author/references/catalog-mapping.md +16 -0
- package/skills/stageflow-author/references/catalog-write-conventions.md +1 -1
- package/skills/stageflow-author/references/stage-prompt-template.md +4 -4
- package/skills/stageflow-run/SKILL.md +22 -12
- package/skills/stageflow-run/references/mcp-call.md +9 -1
- package/skills/stageflow-run/references/task-and-pipeline-selection.md +19 -6
- package/skills/stageflow-run/scripts/mcp-call.mjs +46 -6
- package/skills/stageflow-run/scripts/mcp-call.test.mjs +64 -0
- package/skills/stageflow-session-capture/references/catalog-authoring.md +2 -0
- package/skills/stageflow-setup/SKILL.md +51 -8
- package/dist/ui/assets/index-Da5EHU6M.js +0 -119
|
@@ -16,6 +16,7 @@ export type CommandExecutionInput = {
|
|
|
16
16
|
command: string;
|
|
17
17
|
cwd: string;
|
|
18
18
|
timeout_ms?: number;
|
|
19
|
+
env?: NodeJS.ProcessEnv;
|
|
19
20
|
};
|
|
20
21
|
export type CommandExecutor = {
|
|
21
22
|
run(input: CommandExecutionInput): Promise<CommandExecution>;
|
|
@@ -61,6 +62,8 @@ export type CompletionCheckRunnerInput = {
|
|
|
61
62
|
artifactsDir: string;
|
|
62
63
|
/** Base directory used for a command check without its own cwd. */
|
|
63
64
|
commandWorkingDirectory?: string;
|
|
65
|
+
/** Curated env for command checks; omit to inherit the caller's process env. */
|
|
66
|
+
commandEnv?: NodeJS.ProcessEnv;
|
|
64
67
|
commandExecutor?: CommandExecutor;
|
|
65
68
|
gates?: GateDecisionProvider;
|
|
66
69
|
/** Captured before the agent attempt began. */
|
|
@@ -69,6 +72,12 @@ export type CompletionCheckRunnerInput = {
|
|
|
69
72
|
/** Why the runtime could not establish the required pre-stage baseline. */
|
|
70
73
|
checkoutError?: string;
|
|
71
74
|
checklistAttestations?: readonly ChecklistAttestation[];
|
|
75
|
+
/** Re-runs the Host login check against the stage's own browser session. */
|
|
76
|
+
browserLogin?: () => Promise<{
|
|
77
|
+
state: "logged_in" | "logged_out" | "unknown";
|
|
78
|
+
logged_in: boolean | null;
|
|
79
|
+
url: string;
|
|
80
|
+
}>;
|
|
72
81
|
onCheckStart?: (check: CompletionCheck) => Promise<void> | void;
|
|
73
82
|
onCheckComplete?: (result: CompletionCheckResult) => Promise<void> | void;
|
|
74
83
|
};
|
|
@@ -115,7 +124,12 @@ export type ChecklistCheckEvidence = {
|
|
|
115
124
|
missing_items: string[];
|
|
116
125
|
unexpected_items: string[];
|
|
117
126
|
};
|
|
118
|
-
export type
|
|
127
|
+
export type BrowserLoginCheckEvidence = {
|
|
128
|
+
kind: "browser_login";
|
|
129
|
+
state?: "logged_in" | "logged_out" | "unknown";
|
|
130
|
+
url?: string;
|
|
131
|
+
};
|
|
132
|
+
export type CompletionCheckEvidence = BrowserLoginCheckEvidence | CommandCheckEvidence | ArtifactCheckEvidence | PayloadSchemaCheckEvidence | GateCheckEvidence | CheckoutChangesCheckEvidence | ChecklistCheckEvidence;
|
|
119
133
|
export type CompletionCheckResult = {
|
|
120
134
|
check_id: string;
|
|
121
135
|
check_type: CompletionCheck["type"];
|
|
@@ -3,7 +3,12 @@ import { spawn } from "node:child_process";
|
|
|
3
3
|
import { lstat, readFile } from "node:fs/promises";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { assertEnvelopePayload } from "../envelope/payloadSchema.js";
|
|
6
|
+
import { resolveBashPath } from "../preflight/bash.js";
|
|
7
|
+
import { redactString } from "../logging/redact.js";
|
|
8
|
+
import { getNamedSecrets } from "../logging/namedSecrets.js";
|
|
9
|
+
import { signalProcessGroup } from "./stageProcessLauncher.js";
|
|
6
10
|
const MAX_COMMAND_OUTPUT_BYTES = 64 * 1024;
|
|
11
|
+
const COMMAND_KILL_ESCALATE_MS = 2000;
|
|
7
12
|
function captureOutput(chunks, chunk, currentSize) {
|
|
8
13
|
const remaining = MAX_COMMAND_OUTPUT_BYTES - currentSize;
|
|
9
14
|
if (remaining <= 0)
|
|
@@ -23,19 +28,26 @@ export const nodeCommandExecutor = {
|
|
|
23
28
|
let timedOut = false;
|
|
24
29
|
let settled = false;
|
|
25
30
|
let timeout;
|
|
31
|
+
let escalateTimer;
|
|
26
32
|
const finish = (result) => {
|
|
27
33
|
if (settled)
|
|
28
34
|
return;
|
|
29
35
|
settled = true;
|
|
30
36
|
if (timeout)
|
|
31
37
|
clearTimeout(timeout);
|
|
38
|
+
// When timed out, keep escalateTimer so SIGKILL still runs after the
|
|
39
|
+
// grace window even if the parent already exited cooperatively.
|
|
40
|
+
if (escalateTimer && !timedOut)
|
|
41
|
+
clearTimeout(escalateTimer);
|
|
32
42
|
resolve(result);
|
|
33
43
|
};
|
|
34
44
|
let child;
|
|
35
45
|
try {
|
|
36
|
-
|
|
46
|
+
const bash = resolveBashPath(input.env ?? process.env);
|
|
47
|
+
child = spawn(bash, ["-c", input.command], {
|
|
37
48
|
cwd: input.cwd,
|
|
38
|
-
|
|
49
|
+
env: input.env,
|
|
50
|
+
detached: true,
|
|
39
51
|
stdio: ["ignore", "pipe", "pipe"],
|
|
40
52
|
});
|
|
41
53
|
}
|
|
@@ -55,6 +67,12 @@ export const nodeCommandExecutor = {
|
|
|
55
67
|
child.stderr?.on("data", (data) => {
|
|
56
68
|
stderrSize = captureOutput(stderr, Buffer.from(data), stderrSize);
|
|
57
69
|
});
|
|
70
|
+
child.once("exit", () => {
|
|
71
|
+
if (timedOut) {
|
|
72
|
+
// Parent may exit on SIGTERM while SIGTERM-proof grandchildren remain.
|
|
73
|
+
signalProcessGroup(child.pid, "SIGKILL");
|
|
74
|
+
}
|
|
75
|
+
});
|
|
58
76
|
child.once("error", (error) => {
|
|
59
77
|
finish({
|
|
60
78
|
exit_code: null,
|
|
@@ -75,7 +93,12 @@ export const nodeCommandExecutor = {
|
|
|
75
93
|
if (input.timeout_ms !== undefined) {
|
|
76
94
|
timeout = setTimeout(() => {
|
|
77
95
|
timedOut = true;
|
|
78
|
-
child.
|
|
96
|
+
const pid = child.pid;
|
|
97
|
+
signalProcessGroup(pid, "SIGTERM");
|
|
98
|
+
escalateTimer = setTimeout(() => {
|
|
99
|
+
// Always escalate after the grace window regardless of exited.
|
|
100
|
+
signalProcessGroup(pid, "SIGKILL");
|
|
101
|
+
}, COMMAND_KILL_ESCALATE_MS);
|
|
79
102
|
}, input.timeout_ms);
|
|
80
103
|
}
|
|
81
104
|
});
|
|
@@ -101,16 +124,31 @@ async function runCommandCheck(check, input) {
|
|
|
101
124
|
const cwd = resolveCommandCwd(check, base);
|
|
102
125
|
const executor = input.commandExecutor ?? nodeCommandExecutor;
|
|
103
126
|
try {
|
|
104
|
-
const execution = await executor.run({
|
|
127
|
+
const execution = await executor.run({
|
|
128
|
+
command: check.run,
|
|
129
|
+
cwd,
|
|
130
|
+
timeout_ms: check.timeout_ms,
|
|
131
|
+
...(input.commandEnv !== undefined ? { env: input.commandEnv } : {}),
|
|
132
|
+
});
|
|
105
133
|
const evidence = {
|
|
106
134
|
kind: "command",
|
|
107
135
|
command: check.run,
|
|
108
136
|
cwd,
|
|
109
137
|
exit_code: execution.exit_code,
|
|
110
|
-
stdout: execution.stdout,
|
|
111
|
-
|
|
138
|
+
stdout: redactString(execution.stdout, {
|
|
139
|
+
namedSecrets: getNamedSecrets(),
|
|
140
|
+
}),
|
|
141
|
+
stderr: redactString(execution.stderr, {
|
|
142
|
+
namedSecrets: getNamedSecrets(),
|
|
143
|
+
}),
|
|
112
144
|
timed_out: execution.timed_out,
|
|
113
|
-
...(execution.error !== undefined
|
|
145
|
+
...(execution.error !== undefined
|
|
146
|
+
? {
|
|
147
|
+
error: redactString(execution.error, {
|
|
148
|
+
namedSecrets: getNamedSecrets(),
|
|
149
|
+
}),
|
|
150
|
+
}
|
|
151
|
+
: {}),
|
|
114
152
|
};
|
|
115
153
|
if (execution.timed_out)
|
|
116
154
|
return result(check, "failed", evidence, "command timed out");
|
|
@@ -326,6 +364,26 @@ function runChecklistCheck(check, input) {
|
|
|
326
364
|
}
|
|
327
365
|
return result(check, "passed", evidence);
|
|
328
366
|
}
|
|
367
|
+
async function runBrowserLoginCheck(check, input) {
|
|
368
|
+
const empty = { kind: "browser_login" };
|
|
369
|
+
if (input.browserLogin === undefined) {
|
|
370
|
+
return result(check, "error", empty, "browser_login check requires a browser session");
|
|
371
|
+
}
|
|
372
|
+
try {
|
|
373
|
+
const observed = await input.browserLogin();
|
|
374
|
+
const evidence = {
|
|
375
|
+
kind: "browser_login",
|
|
376
|
+
state: observed.state,
|
|
377
|
+
url: observed.url,
|
|
378
|
+
};
|
|
379
|
+
return observed.logged_in === true
|
|
380
|
+
? result(check, "passed", evidence)
|
|
381
|
+
: result(check, "failed", evidence, `the Host login check still sees a ${observed.state === "unknown" ? "session it cannot confirm" : "logged-out session"}`);
|
|
382
|
+
}
|
|
383
|
+
catch (error) {
|
|
384
|
+
return result(check, "error", empty, error instanceof Error ? error.message : String(error));
|
|
385
|
+
}
|
|
386
|
+
}
|
|
329
387
|
async function runCheck(check, input) {
|
|
330
388
|
switch (check.type) {
|
|
331
389
|
case "command":
|
|
@@ -340,6 +398,8 @@ async function runCheck(check, input) {
|
|
|
340
398
|
return runCheckoutChangesCheck(check, input);
|
|
341
399
|
case "checklist":
|
|
342
400
|
return runChecklistCheck(check, input);
|
|
401
|
+
case "browser_login":
|
|
402
|
+
return runBrowserLoginCheck(check, input);
|
|
343
403
|
}
|
|
344
404
|
}
|
|
345
405
|
/**
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import os from "node:os";
|
|
2
|
+
export type ContainerLimits = {
|
|
3
|
+
memoryLimitBytes: number | undefined;
|
|
4
|
+
maxActiveStageProcesses: number;
|
|
5
|
+
maxOldSpaceSizeMb: number;
|
|
6
|
+
source: "cgroup-v2" | "cgroup-v1" | "fallback";
|
|
7
|
+
};
|
|
8
|
+
export declare function readContainerMemoryLimit(roots?: readonly string[]): {
|
|
9
|
+
bytes: number | undefined;
|
|
10
|
+
source: ContainerLimits["source"];
|
|
11
|
+
};
|
|
12
|
+
export declare function deriveContainerLimits(memoryLimitBytes: number | undefined, source?: ContainerLimits["source"]): ContainerLimits;
|
|
13
|
+
export declare function getContainerLimits(): ContainerLimits;
|
|
14
|
+
export declare function resetContainerLimitsForTests(): void;
|
|
15
|
+
/** Test hook: prove sizing never consults os.totalmem. */
|
|
16
|
+
export declare function assertNoOsTotalmemInSizing(): typeof os.totalmem;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
const HOST_RESERVE_MIB = 512;
|
|
4
|
+
const WORKER_BUDGET_MIB = 512;
|
|
5
|
+
const MAX_CAP = 8;
|
|
6
|
+
const FALLBACK_CAP = 4;
|
|
7
|
+
const FALLBACK_HEAP_MIB = 512;
|
|
8
|
+
const V1_SENTINEL = 9223372036854771712n;
|
|
9
|
+
function parseCgroupMemory(raw) {
|
|
10
|
+
const trimmed = raw.trim();
|
|
11
|
+
if (trimmed === "" || trimmed === "max")
|
|
12
|
+
return undefined;
|
|
13
|
+
let n;
|
|
14
|
+
try {
|
|
15
|
+
n = BigInt(trimmed);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
if (n <= 0n || n >= V1_SENTINEL)
|
|
21
|
+
return undefined;
|
|
22
|
+
if (n > BigInt(Number.MAX_SAFE_INTEGER))
|
|
23
|
+
return undefined;
|
|
24
|
+
return Number(n);
|
|
25
|
+
}
|
|
26
|
+
export function readContainerMemoryLimit(roots = ["/sys/fs/cgroup"]) {
|
|
27
|
+
for (const root of roots) {
|
|
28
|
+
const v2 = `${root}/memory.max`;
|
|
29
|
+
if (existsSync(v2)) {
|
|
30
|
+
try {
|
|
31
|
+
const bytes = parseCgroupMemory(readFileSync(v2, "utf8"));
|
|
32
|
+
return { bytes, source: bytes === undefined ? "fallback" : "cgroup-v2" };
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
// continue
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const v1 = `${root}/memory/memory.limit_in_bytes`;
|
|
39
|
+
if (existsSync(v1)) {
|
|
40
|
+
try {
|
|
41
|
+
const bytes = parseCgroupMemory(readFileSync(v1, "utf8"));
|
|
42
|
+
return { bytes, source: bytes === undefined ? "fallback" : "cgroup-v1" };
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
// continue
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return { bytes: undefined, source: "fallback" };
|
|
50
|
+
}
|
|
51
|
+
export function deriveContainerLimits(memoryLimitBytes, source = "fallback") {
|
|
52
|
+
if (memoryLimitBytes === undefined) {
|
|
53
|
+
return {
|
|
54
|
+
memoryLimitBytes: undefined,
|
|
55
|
+
maxActiveStageProcesses: FALLBACK_CAP,
|
|
56
|
+
maxOldSpaceSizeMb: FALLBACK_HEAP_MIB,
|
|
57
|
+
source: "fallback",
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
const limitMib = Math.floor(memoryLimitBytes / (1024 * 1024));
|
|
61
|
+
const workerBudget = Math.max(1, limitMib - HOST_RESERVE_MIB);
|
|
62
|
+
const cap = Math.min(MAX_CAP, Math.max(1, Math.floor(workerBudget / WORKER_BUDGET_MIB)));
|
|
63
|
+
return {
|
|
64
|
+
memoryLimitBytes,
|
|
65
|
+
maxActiveStageProcesses: cap,
|
|
66
|
+
maxOldSpaceSizeMb: WORKER_BUDGET_MIB,
|
|
67
|
+
source,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
let cached;
|
|
71
|
+
export function getContainerLimits() {
|
|
72
|
+
if (cached === undefined) {
|
|
73
|
+
const { bytes, source } = readContainerMemoryLimit();
|
|
74
|
+
cached = deriveContainerLimits(bytes, source);
|
|
75
|
+
}
|
|
76
|
+
return cached;
|
|
77
|
+
}
|
|
78
|
+
export function resetContainerLimitsForTests() {
|
|
79
|
+
cached = undefined;
|
|
80
|
+
}
|
|
81
|
+
/** Test hook: prove sizing never consults os.totalmem. */
|
|
82
|
+
export function assertNoOsTotalmemInSizing() {
|
|
83
|
+
return os.totalmem;
|
|
84
|
+
}
|
|
@@ -11,6 +11,8 @@ export type ResolveCredentialBindingOptions = {
|
|
|
11
11
|
};
|
|
12
12
|
export declare function sfOwnedAgentDir(): string;
|
|
13
13
|
export declare function sfOwnedAuthPath(): string;
|
|
14
|
+
export declare const PI_HOME_AUTH_PATH_ENV = "STAGEFLOW_PI_HOME_AUTH_PATH";
|
|
15
|
+
/** A stage worker's HOME is an empty attempt dir, so the Host passes its own Pi auth path through the environment. */
|
|
14
16
|
export declare function piHomeAuthPath(override?: string): string;
|
|
15
17
|
export declare function isUsableAuthFile(authPath: string): boolean;
|
|
16
18
|
export declare function ensureSfOwnedAuthStore(): string;
|
|
@@ -11,8 +11,11 @@ export function sfOwnedAgentDir() {
|
|
|
11
11
|
export function sfOwnedAuthPath() {
|
|
12
12
|
return path.join(sfOwnedAgentDir(), "auth.json");
|
|
13
13
|
}
|
|
14
|
+
export const PI_HOME_AUTH_PATH_ENV = "STAGEFLOW_PI_HOME_AUTH_PATH";
|
|
15
|
+
/** A stage worker's HOME is an empty attempt dir, so the Host passes its own Pi auth path through the environment. */
|
|
14
16
|
export function piHomeAuthPath(override) {
|
|
15
17
|
return (override ??
|
|
18
|
+
(process.env[PI_HOME_AUTH_PATH_ENV] || undefined) ??
|
|
16
19
|
path.join(os.homedir(), ".pi", "agent", "auth.json"));
|
|
17
20
|
}
|
|
18
21
|
export function isUsableAuthFile(authPath) {
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export type MaterialiseCopyResult = {
|
|
2
|
+
destPath: string;
|
|
3
|
+
mode: number;
|
|
4
|
+
};
|
|
5
|
+
export declare class CredentialMaterialisationError extends Error {
|
|
6
|
+
readonly code: "symlink_rejected" | "escape_rejected" | "source_missing" | "not_a_file";
|
|
7
|
+
constructor(message: string, code: CredentialMaterialisationError["code"]);
|
|
8
|
+
}
|
|
9
|
+
export declare function attemptCredentialsDir(attemptDir: string, secretName: string): string;
|
|
10
|
+
/** Copy a Host source file into attempt credentials with mode 0400. */
|
|
11
|
+
export declare function materialiseCredentialFile(options: {
|
|
12
|
+
sourcePath: string;
|
|
13
|
+
destDir: string;
|
|
14
|
+
destBasename?: string;
|
|
15
|
+
allowedRoot?: string;
|
|
16
|
+
}): MaterialiseCopyResult;
|
|
17
|
+
export declare function materialiseSecretBytes(options: {
|
|
18
|
+
contents: string | Buffer;
|
|
19
|
+
destDir: string;
|
|
20
|
+
destBasename: string;
|
|
21
|
+
}): MaterialiseCopyResult;
|
|
22
|
+
export declare function cleanupCredentialsDir(attemptDir: string): void;
|
|
23
|
+
export declare function stageAskpassHelperPath(home?: string): string;
|
|
24
|
+
export declare function ensureStageAskpassHelper(home?: string): string;
|
|
25
|
+
export declare function readFileCredentialRegistry(home?: string): Record<string, {
|
|
26
|
+
source: string;
|
|
27
|
+
pointerVar: string;
|
|
28
|
+
}>;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { chmodSync, copyFileSync, existsSync, lstatSync, mkdirSync, readFileSync, realpathSync, rmSync, writeFileSync, } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { ensureGlobalHome, globalStageflowHome } from "../project/globalHome.js";
|
|
4
|
+
export class CredentialMaterialisationError extends Error {
|
|
5
|
+
code;
|
|
6
|
+
constructor(message, code) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = "CredentialMaterialisationError";
|
|
9
|
+
this.code = code;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export function attemptCredentialsDir(attemptDir, secretName) {
|
|
13
|
+
return path.join(attemptDir, "credentials", secretName);
|
|
14
|
+
}
|
|
15
|
+
/** Copy a Host source file into attempt credentials with mode 0400. */
|
|
16
|
+
export function materialiseCredentialFile(options) {
|
|
17
|
+
const sourcePath = path.resolve(options.sourcePath);
|
|
18
|
+
let stat;
|
|
19
|
+
try {
|
|
20
|
+
stat = lstatSync(sourcePath);
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
throw new CredentialMaterialisationError(`credential source missing: ${sourcePath}`, "source_missing");
|
|
24
|
+
}
|
|
25
|
+
if (stat.isSymbolicLink()) {
|
|
26
|
+
throw new CredentialMaterialisationError(`credential source must not be a symlink: ${sourcePath}`, "symlink_rejected");
|
|
27
|
+
}
|
|
28
|
+
if (!stat.isFile()) {
|
|
29
|
+
throw new CredentialMaterialisationError(`credential source must be a regular file: ${sourcePath}`, "not_a_file");
|
|
30
|
+
}
|
|
31
|
+
const realSource = realpathSync(sourcePath);
|
|
32
|
+
if (options.allowedRoot !== undefined) {
|
|
33
|
+
let root = path.resolve(options.allowedRoot);
|
|
34
|
+
try {
|
|
35
|
+
root = realpathSync(root);
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
// allowed root may not exist yet; keep resolved path
|
|
39
|
+
}
|
|
40
|
+
if (realSource !== root && !realSource.startsWith(root + path.sep)) {
|
|
41
|
+
throw new CredentialMaterialisationError(`credential source escapes allowed root: ${sourcePath}`, "escape_rejected");
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
mkdirSync(options.destDir, { recursive: true, mode: 0o700 });
|
|
45
|
+
const destPath = path.join(options.destDir, options.destBasename ?? path.basename(realSource));
|
|
46
|
+
copyFileSync(realSource, destPath);
|
|
47
|
+
try {
|
|
48
|
+
chmodSync(destPath, 0o400);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
// best-effort on non-POSIX
|
|
52
|
+
}
|
|
53
|
+
return { destPath, mode: 0o400 };
|
|
54
|
+
}
|
|
55
|
+
export function materialiseSecretBytes(options) {
|
|
56
|
+
mkdirSync(options.destDir, { recursive: true, mode: 0o700 });
|
|
57
|
+
const destPath = path.join(options.destDir, options.destBasename);
|
|
58
|
+
writeFileSync(destPath, options.contents, { mode: 0o400 });
|
|
59
|
+
try {
|
|
60
|
+
chmodSync(destPath, 0o400);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// best-effort
|
|
64
|
+
}
|
|
65
|
+
return { destPath, mode: 0o400 };
|
|
66
|
+
}
|
|
67
|
+
export function cleanupCredentialsDir(attemptDir) {
|
|
68
|
+
const root = path.join(attemptDir, "credentials");
|
|
69
|
+
if (!existsSync(root))
|
|
70
|
+
return;
|
|
71
|
+
rmSync(root, { recursive: true, force: true });
|
|
72
|
+
}
|
|
73
|
+
const STAGE_ASKPASS_BASENAME = "git-askpass-stage";
|
|
74
|
+
const STAGE_ASKPASS_SCRIPT = `#!/bin/sh
|
|
75
|
+
prompt=\${1-}
|
|
76
|
+
case "\$prompt" in
|
|
77
|
+
*Username*|*username*)
|
|
78
|
+
printf '%s\\n' 'x-access-token'
|
|
79
|
+
;;
|
|
80
|
+
*)
|
|
81
|
+
token=
|
|
82
|
+
if [ -n "\${STAGEFLOW_GIT_ASKPASS_TOKEN_FILE-}" ] && [ -f "\$STAGEFLOW_GIT_ASKPASS_TOKEN_FILE" ]; then
|
|
83
|
+
token=\$(cat "\$STAGEFLOW_GIT_ASKPASS_TOKEN_FILE")
|
|
84
|
+
fi
|
|
85
|
+
printf '%s\\n' "\$token"
|
|
86
|
+
;;
|
|
87
|
+
esac
|
|
88
|
+
`;
|
|
89
|
+
export function stageAskpassHelperPath(home = globalStageflowHome()) {
|
|
90
|
+
return path.join(home, STAGE_ASKPASS_BASENAME);
|
|
91
|
+
}
|
|
92
|
+
export function ensureStageAskpassHelper(home) {
|
|
93
|
+
const resolvedHome = home ?? ensureGlobalHome();
|
|
94
|
+
mkdirSync(resolvedHome, { recursive: true });
|
|
95
|
+
const askpass = stageAskpassHelperPath(resolvedHome);
|
|
96
|
+
writeFileSync(askpass, STAGE_ASKPASS_SCRIPT, { encoding: "utf8", mode: 0o700 });
|
|
97
|
+
try {
|
|
98
|
+
chmodSync(askpass, 0o700);
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
// best-effort
|
|
102
|
+
}
|
|
103
|
+
return askpass;
|
|
104
|
+
}
|
|
105
|
+
export function readFileCredentialRegistry(home = globalStageflowHome()) {
|
|
106
|
+
const registryPath = path.join(home, "secrets", "file-credentials.json");
|
|
107
|
+
if (!existsSync(registryPath))
|
|
108
|
+
return {};
|
|
109
|
+
try {
|
|
110
|
+
const raw = JSON.parse(readFileSync(registryPath, "utf8"));
|
|
111
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
112
|
+
return {};
|
|
113
|
+
const out = {};
|
|
114
|
+
for (const [name, entry] of Object.entries(raw)) {
|
|
115
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry))
|
|
116
|
+
continue;
|
|
117
|
+
const e = entry;
|
|
118
|
+
if (typeof e.source !== "string" || typeof e.pointerVar !== "string") {
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
out[name] = { source: e.source, pointerVar: e.pointerVar };
|
|
122
|
+
}
|
|
123
|
+
return out;
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
return {};
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { RunStore } from "../runstore/port.js";
|
|
2
|
+
import type { TriggerFireEvent, TriggerSourcePort } from "./triggerPort.js";
|
|
3
|
+
export declare const DEFAULT_EMAIL_RECONNECT_BASE_DELAY_MS = 1000;
|
|
4
|
+
export declare const DEFAULT_EMAIL_RECONNECT_MAX_DELAY_MS = 30000;
|
|
5
|
+
export declare const EMAIL_TEXT_EXCERPT_MAX_CHARS = 2000;
|
|
6
|
+
export type NormalizedEmailMessage = {
|
|
7
|
+
uid: number;
|
|
8
|
+
from: string;
|
|
9
|
+
subject: string;
|
|
10
|
+
date: string;
|
|
11
|
+
text: string;
|
|
12
|
+
};
|
|
13
|
+
export type EmailClientConfig = {
|
|
14
|
+
host: string;
|
|
15
|
+
port: number;
|
|
16
|
+
user: string;
|
|
17
|
+
password: string;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Narrow, test-friendly seam over "one IMAP/IDLE mailbox connection". The
|
|
21
|
+
* default implementation adapts `imapflow`'s `ImapFlow`; tests inject a fake
|
|
22
|
+
* so no real mailbox is ever contacted.
|
|
23
|
+
*/
|
|
24
|
+
export type EmailImapClient = {
|
|
25
|
+
connect(): Promise<{
|
|
26
|
+
uidNext: number;
|
|
27
|
+
}>;
|
|
28
|
+
idle(): void;
|
|
29
|
+
fetchNewMessages(sinceUid: number): Promise<NormalizedEmailMessage[]>;
|
|
30
|
+
close(): Promise<void>;
|
|
31
|
+
onExists(listener: () => void): void;
|
|
32
|
+
onClose(listener: () => void): void;
|
|
33
|
+
onError(listener: (err: Error) => void): void;
|
|
34
|
+
};
|
|
35
|
+
export type EmailSourceOptions = {
|
|
36
|
+
store: RunStore;
|
|
37
|
+
cwd?: string;
|
|
38
|
+
logError?: (message: string) => void;
|
|
39
|
+
env?: NodeJS.ProcessEnv;
|
|
40
|
+
/** Injectable client factory so tests never hit a real mailbox. */
|
|
41
|
+
createEmailClient?: (config: EmailClientConfig) => EmailImapClient;
|
|
42
|
+
reconnectBaseDelayMs?: number;
|
|
43
|
+
reconnectMaxDelayMs?: number;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* `TriggerSourcePort` adapter for `event`-kind triggers whose `event.source`
|
|
47
|
+
* starts with `email.`. Unlike the poll-based adapters this one is push-based:
|
|
48
|
+
* on `start()` it groups triggers by distinct mailbox (`host`+`port`+`user`),
|
|
49
|
+
* opens exactly one real IMAP/IDLE connection per mailbox regardless of how
|
|
50
|
+
* many triggers watch it, and reacts to the server's new-message
|
|
51
|
+
* notification instead of ticking on an interval. A dropped connection
|
|
52
|
+
* reconnects with bounded exponential backoff rather than going dark.
|
|
53
|
+
*/
|
|
54
|
+
export declare class EmailSource implements TriggerSourcePort {
|
|
55
|
+
private readonly store;
|
|
56
|
+
private readonly cwd;
|
|
57
|
+
private readonly logError;
|
|
58
|
+
private readonly env;
|
|
59
|
+
private readonly createEmailClient;
|
|
60
|
+
private readonly reconnectBaseDelayMs;
|
|
61
|
+
private readonly reconnectMaxDelayMs;
|
|
62
|
+
private readonly connections;
|
|
63
|
+
private stopped;
|
|
64
|
+
constructor(options: EmailSourceOptions);
|
|
65
|
+
start(onFire: (event: TriggerFireEvent) => Promise<void>): Promise<void>;
|
|
66
|
+
stop(): Promise<void>;
|
|
67
|
+
private discover;
|
|
68
|
+
private connectMailbox;
|
|
69
|
+
private scheduleReconnect;
|
|
70
|
+
private processNewMail;
|
|
71
|
+
private fireSafely;
|
|
72
|
+
}
|