stageflow 0.32.0 → 0.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/dist/agent/adapterSpill.d.ts +14 -0
- package/dist/agent/adapterSpill.js +83 -0
- package/dist/agent/agentBackend.d.ts +2 -2
- package/dist/agent/agentBackend.js +2 -2
- package/dist/agent/claudeAdapter.d.ts +13 -2
- package/dist/agent/claudeAdapter.js +50 -6
- package/dist/agent/cursorProvider.d.ts +3 -0
- package/dist/agent/cursorProvider.js +23 -6
- package/dist/agent/fakeAgent.d.ts +3 -3
- package/dist/agent/fakeAgent.js +0 -6
- package/dist/agent/piAdapter.d.ts +2 -2
- package/dist/agent/piAdapter.js +116 -15
- package/dist/agent/piIsolatedMcp.d.ts +1 -0
- package/dist/agent/piIsolatedMcp.js +19 -1
- package/dist/agent/piIsolatedMcpProbe.d.ts +11 -0
- package/dist/agent/piIsolatedMcpProbe.js +20 -0
- package/dist/agent/port.d.ts +2 -2
- package/dist/agent/providerAuth.d.ts +6 -0
- package/dist/agent/providerAuth.js +86 -17
- package/dist/agent/{resolveAgentPort.d.ts → resolveStagePort.d.ts} +8 -6
- package/dist/agent/{resolveAgentPort.js → resolveStagePort.js} +13 -9
- package/dist/agent/stageTurnDriver.d.ts +33 -0
- package/dist/agent/stageTurnDriver.js +64 -0
- package/dist/agent/toolOutputBudget.d.ts +46 -0
- package/dist/agent/toolOutputBudget.js +97 -0
- package/dist/agent/toolOutputBudgetExtension.d.ts +22 -0
- package/dist/agent/toolOutputBudgetExtension.js +141 -0
- package/dist/agent/toolOutputSpill.d.ts +34 -0
- package/dist/agent/toolOutputSpill.js +85 -0
- package/dist/browser/agentBrowserLiveViewRelay.d.ts +41 -0
- package/dist/browser/agentBrowserLiveViewRelay.js +801 -0
- package/dist/browser/anchor.d.ts +2 -0
- package/dist/browser/anchor.js +2 -1
- package/dist/browser/auditSink.d.ts +8 -0
- package/dist/browser/browserHost.d.ts +29 -0
- package/dist/browser/browserSweep.d.ts +4 -1
- package/dist/browser/browserSweep.js +7 -0
- package/dist/browser/browserTeardown.d.ts +1 -0
- package/dist/browser/browserTeardown.js +32 -2
- package/dist/browser/containerBrowserEndpoint.d.ts +11 -0
- package/dist/browser/containerBrowserEndpoint.js +57 -0
- package/dist/browser/containerBrowserHost.d.ts +24 -0
- package/dist/browser/containerBrowserHost.js +147 -0
- package/dist/browser/dockerSandboxOrchestrator.d.ts +26 -0
- package/dist/browser/dockerSandboxOrchestrator.js +142 -0
- package/dist/browser/fakeLiveViewRelay.d.ts +15 -0
- package/dist/browser/fakeLiveViewRelay.js +94 -0
- package/dist/browser/fakeLiveViewSource.d.ts +6 -0
- package/dist/browser/fakeLiveViewSource.js +16 -0
- package/dist/browser/fakeRemoteBrowserHost.d.ts +2 -1
- package/dist/browser/fakeRemoteBrowserHost.js +2 -1
- package/dist/browser/fakeSandboxOrchestrator.d.ts +9 -0
- package/dist/browser/fakeSandboxOrchestrator.js +44 -0
- package/dist/browser/gateHandoff.d.ts +0 -2
- package/dist/browser/gateHandoff.js +5 -11
- package/dist/browser/hostCapabilities.d.ts +23 -0
- package/dist/browser/hostCapabilities.js +23 -0
- package/dist/browser/humanLogin.d.ts +2 -2
- package/dist/browser/humanLogin.js +11 -2
- package/dist/browser/liveViewPersisted.d.ts +11 -0
- package/dist/browser/liveViewPersisted.js +22 -0
- package/dist/browser/liveViewRelay.d.ts +76 -0
- package/dist/browser/liveViewRelay.js +1 -0
- package/dist/browser/liveViewSessions.d.ts +25 -0
- package/dist/browser/liveViewSessions.js +139 -0
- package/dist/browser/liveViewSource.d.ts +25 -0
- package/dist/browser/liveViewSource.js +7 -0
- package/dist/browser/liveViewTickets.d.ts +46 -0
- package/dist/browser/liveViewTickets.js +122 -0
- package/dist/browser/localBrowserHost.d.ts +10 -0
- package/dist/browser/localBrowserHost.js +53 -7
- package/dist/browser/ownerScope.d.ts +10 -0
- package/dist/browser/ownerScope.js +6 -0
- package/dist/browser/profileStore.d.ts +5 -2
- package/dist/browser/profileStore.js +3 -5
- package/dist/browser/sandboxOrchestrator.d.ts +60 -0
- package/dist/browser/sandboxOrchestrator.js +8 -0
- package/dist/browser/sessionApiSandboxOrchestrator.d.ts +34 -0
- package/dist/browser/sessionApiSandboxOrchestrator.js +108 -0
- package/dist/browser/stageBrowserEnv.d.ts +7 -0
- package/dist/browser/stageBrowserEnv.js +53 -15
- package/dist/browser/stageHandoff.d.ts +47 -0
- package/dist/browser/stageHandoff.js +101 -0
- package/dist/browser/stageProfileLock.d.ts +1 -0
- package/dist/browser/stageProfileLock.js +1 -3
- package/dist/browser/volumeProfileStore.d.ts +7 -0
- package/dist/browser/volumeProfileStore.js +35 -0
- package/dist/cli/browserCommand.d.ts +3 -1
- package/dist/cli/browserCommand.js +25 -20
- package/dist/cli/resolveCliProjectRoot.d.ts +7 -0
- package/dist/cli/resolveCliProjectRoot.js +27 -0
- package/dist/cli/runCommand.d.ts +1 -1
- package/dist/cli/runCommand.js +59 -17
- package/dist/cli/skillsCommand.d.ts +20 -0
- package/dist/cli/skillsCommand.js +74 -31
- package/dist/cli/validateCommand.d.ts +1 -1
- package/dist/cli/validateCommand.js +22 -4
- package/dist/cli.js +4 -4
- package/dist/config/browseCatalog.d.ts +2 -0
- package/dist/config/browseCatalog.js +6 -0
- package/dist/config/catalogRelativePath.d.ts +4 -0
- package/dist/config/catalogRelativePath.js +37 -9
- package/dist/config/createStage.d.ts +1 -0
- package/dist/config/createStage.js +11 -2
- package/dist/config/createTask.d.ts +30 -0
- package/dist/config/createTask.js +161 -0
- package/dist/config/createTrigger.d.ts +15 -0
- package/dist/config/createTrigger.js +32 -25
- package/dist/config/draftPackage.d.ts +41 -0
- package/dist/config/draftPackage.js +216 -23
- package/dist/config/ensureCatalogScanRoot.d.ts +2 -1
- package/dist/config/ensureCatalogScanRoot.js +6 -2
- package/dist/config/findTaskInCatalog.d.ts +33 -0
- package/dist/config/findTaskInCatalog.js +69 -0
- package/dist/config/hostConfig.d.ts +21 -0
- package/dist/config/hostConfig.js +113 -1
- package/dist/config/importTask.d.ts +19 -0
- package/dist/config/importTask.js +133 -0
- package/dist/config/installSkillRequest.d.ts +40 -0
- package/dist/config/installSkillRequest.js +286 -0
- package/dist/config/listConfig.d.ts +0 -16
- package/dist/config/listConfig.js +0 -3
- package/dist/config/loadOutcome.d.ts +11 -6
- package/dist/config/loadPipeline.js +0 -1
- package/dist/config/loadStage.js +2 -0
- package/dist/config/loadStageflowManifest.js +4 -1
- package/dist/config/loadTask.js +2 -0
- package/dist/config/loadTrigger.js +2 -0
- package/dist/config/mergePipelineIncludes.js +3 -0
- package/dist/config/normalizePipelineStageEntry.js +10 -1
- package/dist/config/printTargetYaml.js +0 -1
- package/dist/config/publishDraftPackage.d.ts +5 -1
- package/dist/config/publishDraftPackage.js +4 -1
- package/dist/config/resolveCatalogRoots.d.ts +4 -1
- package/dist/config/resolveCatalogRoots.js +18 -1
- package/dist/config/skillUsageIndex.d.ts +6 -0
- package/dist/config/skillUsageIndex.js +39 -0
- package/dist/config/stageBrowser.js +13 -0
- package/dist/config/triggerAdapterStatus.d.ts +11 -0
- package/dist/config/triggerAdapterStatus.js +90 -0
- package/dist/config/triggerCatalog.d.ts +41 -2
- package/dist/config/triggerCatalog.js +107 -15
- package/dist/config/updateTask.d.ts +30 -0
- package/dist/config/updateTask.js +119 -0
- package/dist/config/updateTrigger.d.ts +38 -0
- package/dist/config/updateTrigger.js +220 -0
- package/dist/config/validateCatalog.d.ts +6 -2
- package/dist/config/validateCatalog.js +48 -7
- package/dist/config/workshopCatalogFilenames.d.ts +37 -0
- package/dist/config/workshopCatalogFilenames.js +125 -0
- package/dist/config/workshopCatalogRepair.d.ts +7 -0
- package/dist/config/workshopCatalogRepair.js +144 -0
- package/dist/config/yamlParsePosition.d.ts +4 -0
- package/dist/config/yamlParsePosition.js +9 -0
- package/dist/hosted/containment.d.ts +3 -0
- package/dist/hosted/containment.js +36 -0
- package/dist/hosted/errors.d.ts +21 -0
- package/dist/hosted/errors.js +30 -0
- package/dist/hosted/packageSkills.d.ts +3 -0
- package/dist/hosted/packageSkills.js +80 -0
- package/dist/hosted/runtime.d.ts +12 -0
- package/dist/hosted/runtime.js +596 -0
- package/dist/hosted/sequencer.d.ts +28 -0
- package/dist/hosted/sequencer.js +129 -0
- package/dist/hosted/translate.d.ts +3 -0
- package/dist/hosted/translate.js +43 -0
- package/dist/hosted/types.d.ts +108 -0
- package/dist/hosted/types.js +10 -0
- package/dist/index.d.ts +9 -1
- package/dist/index.js +6 -0
- package/dist/mcp/getStartedTool.js +15 -6
- package/dist/mcp/triggerTools.js +2 -8
- package/dist/operatorAgent/agentPort.d.ts +11 -0
- package/dist/operatorAgent/agentPort.js +12 -0
- package/dist/operatorAgent/index.d.ts +1 -0
- package/dist/operatorAgent/index.js +1 -0
- package/dist/operatorAgent/piModel.js +26 -6
- package/dist/operatorAgent/profiles/workshopAuthorPlaybook.d.ts +1 -1
- package/dist/operatorAgent/profiles/workshopAuthorPlaybook.js +4 -2
- package/dist/operatorAgent/profiles/workshopAuthorTools.js +103 -16
- package/dist/package-meta.d.ts +1 -1
- package/dist/package-meta.js +1 -1
- package/dist/project/ensureProjectRootsFromEnv.d.ts +3 -0
- package/dist/project/ensureProjectRootsFromEnv.js +22 -0
- package/dist/project/globalHome.d.ts +1 -0
- package/dist/project/globalHome.js +18 -0
- package/dist/project/workspaceCatalog.d.ts +10 -0
- package/dist/project/workspaceCatalog.js +91 -0
- package/dist/projection/projectRun.d.ts +0 -1
- package/dist/projection/projectRun.js +0 -1
- package/dist/runstore/backup.js +14 -4
- package/dist/runstore/port.d.ts +11 -1
- package/dist/runstore/restore.js +5 -2
- package/dist/runstore/sqlite/SqliteRunStore.d.ts +8 -0
- package/dist/runstore/sqlite/SqliteRunStore.js +29 -9
- package/dist/runstore/sqlite/migrations/012-trigger-fires.d.ts +7 -0
- package/dist/runstore/sqlite/migrations/012-trigger-fires.js +18 -0
- package/dist/runstore/sqlite/migrations/index.js +2 -0
- package/dist/runstore/stageSnapshot.d.ts +3 -1
- package/dist/runstore/stageSnapshot.js +19 -0
- package/dist/runstore/workspaceLayout.js +27 -0
- package/dist/runstore/writeContainedArtifact.d.ts +1 -0
- package/dist/runstore/writeContainedArtifact.js +52 -0
- package/dist/runtime/containerLimits.d.ts +0 -3
- package/dist/runtime/containerLimits.js +0 -5
- package/dist/runtime/credentialBinding.d.ts +3 -0
- package/dist/runtime/credentialBinding.js +23 -6
- package/dist/runtime/emailSource.js +20 -28
- package/dist/runtime/githubPollSource.js +20 -28
- package/dist/runtime/pipelineRunner.d.ts +4 -4
- package/dist/runtime/pipelineScheduler.d.ts +2 -2
- package/dist/runtime/pipelineScheduler.js +3 -0
- package/dist/runtime/resumeReconstruct.d.ts +2 -2
- package/dist/runtime/resumeTimedOut.d.ts +2 -2
- package/dist/runtime/runManager.d.ts +18 -2
- package/dist/runtime/runManager.js +95 -30
- package/dist/runtime/runRetentionSweep.d.ts +0 -2
- package/dist/runtime/runRetentionSweep.js +0 -8
- package/dist/runtime/runRetryCoordinator.d.ts +2 -2
- package/dist/runtime/scheduleSource.js +15 -24
- package/dist/runtime/stageAttemptBootstrap.d.ts +2 -2
- package/dist/runtime/stageAttemptBootstrap.js +10 -1
- package/dist/runtime/stageProcessLauncher.js +2 -2
- package/dist/runtime/stageRoots.js +12 -1
- package/dist/runtime/stageRunner.d.ts +2 -2
- package/dist/runtime/stageRunner.js +8 -2
- package/dist/runtime/stageWorker.js +2 -2
- package/dist/runtime/triggerPort.d.ts +5 -3
- package/dist/runtime/triggerRunner.d.ts +1 -0
- package/dist/runtime/triggerRunner.js +27 -20
- package/dist/runtime/webhookAccept.d.ts +25 -0
- package/dist/runtime/webhookAccept.js +56 -0
- package/dist/server/bootstrap.d.ts +7 -2
- package/dist/server/bootstrap.js +15 -1
- package/dist/server/controlToken.d.ts +1 -1
- package/dist/server/controlToken.js +18 -2
- package/dist/server/healthSurfaces.d.ts +12 -0
- package/dist/server/healthSurfaces.js +27 -6
- package/dist/server/http.d.ts +19 -10
- package/dist/server/http.js +605 -85
- package/dist/server/liveViewPath.d.ts +9 -0
- package/dist/server/liveViewPath.js +8 -0
- package/dist/server/liveViewRoutes.d.ts +58 -0
- package/dist/server/liveViewRoutes.js +565 -0
- package/dist/server/mcpHost.d.ts +4 -2
- package/dist/server/mcpHost.js +2 -0
- package/dist/server/readCatalogFile.d.ts +29 -0
- package/dist/server/readCatalogFile.js +215 -0
- package/dist/server/triggerRoutes.d.ts +1 -0
- package/dist/server/triggerRoutes.js +200 -73
- package/dist/tools/readEmail.d.ts +3 -3
- package/dist/tools/writeStageArtifact.d.ts +9 -0
- package/dist/tools/writeStageArtifact.js +2 -47
- package/dist/types/pipeline.d.ts +1 -1
- package/dist/types/stage.d.ts +1 -1
- package/dist/types/stageflowManifest.d.ts +1 -1
- package/dist/ui/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
- package/dist/ui/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
- package/dist/ui/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
- package/dist/ui/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
- package/dist/ui/assets/geist-mono-cyrillic-ext-wght-normal-X_5orZeX.woff2 +0 -0
- package/dist/ui/assets/geist-mono-cyrillic-wght-normal-DiZS0aHC.woff2 +0 -0
- package/dist/ui/assets/geist-mono-latin-ext-wght-normal-Bwz-egvJ.woff2 +0 -0
- package/dist/ui/assets/geist-mono-latin-wght-normal-XN7g48iV.woff2 +0 -0
- package/dist/ui/assets/geist-mono-symbols2-wght-normal-CO5SzqOn.woff2 +0 -0
- package/dist/ui/assets/geist-mono-vietnamese-wght-normal-DadHysG0.woff2 +0 -0
- package/dist/ui/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
- package/dist/ui/assets/index-BoFPkKFg.js +256 -0
- package/dist/ui/assets/{index-Bv4p1aPK.css → index-CIPbbBUi.css} +1 -1
- package/dist/ui/index.html +4 -4
- package/dist/workshop/autosave.d.ts +2 -2
- package/dist/workshop/autosave.js +4 -6
- package/dist/workshop/buildStore.d.ts +2 -0
- package/dist/workshop/chatAttachments.d.ts +27 -0
- package/dist/workshop/chatAttachments.js +98 -0
- package/dist/workshop/chatTurn.d.ts +5 -2
- package/dist/workshop/chatTurn.js +22 -18
- package/dist/workshop/sessionMutations.d.ts +17 -0
- package/dist/workshop/sessionMutations.js +107 -0
- package/dist/workshop/sessionStore.d.ts +10 -0
- package/dist/workshop/sessionStore.js +52 -0
- package/dist/workshop/workshopPin.d.ts +4 -3
- package/dist/workshop/workshopPin.js +26 -6
- package/dist/workshop/workshopTranscriptTurn.d.ts +8 -0
- package/dist/workshop/workshopTranscriptTurn.js +46 -0
- package/examples/README.md +1 -1
- package/examples/archify-on-pr/README.md +1 -1
- package/examples/archify-on-pr/archify-on-pr.pipeline.yaml +0 -1
- package/examples/archify-on-pr/author-diagrams.yaml +1 -0
- package/examples/conditional-fork/branch-a.yaml +1 -1
- package/examples/conditional-fork/decide.yaml +2 -1
- package/examples/feature-loop/{implement.yaml → feature-implement.yaml} +1 -1
- package/examples/feature-loop/feature-loop.pipeline.yaml +10 -10
- package/examples/feature-loop/{plan.yaml → feature-plan.yaml} +1 -1
- package/examples/feature-loop/{review.yaml → feature-review.yaml} +1 -1
- package/examples/feedback-loop/{implement.yaml → feedback-implement.yaml} +1 -1
- package/examples/feedback-loop/feedback-loop-wait-human.pipeline.yaml +9 -9
- package/examples/feedback-loop/feedback-loop.pipeline.yaml +9 -9
- package/examples/feedback-loop/{plan.yaml → feedback-plan.yaml} +1 -1
- package/examples/feedback-loop/{review.yaml → feedback-review.yaml} +1 -1
- package/examples/generic-fan-in/{research.yaml → fan-in-research.yaml} +1 -1
- package/examples/generic-fan-in/generic-fan-in-accepted.pipeline.yaml +3 -3
- package/examples/generic-fan-in/generic-fan-in.pipeline.yaml +3 -3
- package/examples/hello-world/{research.yaml → hello-research.yaml} +1 -1
- package/examples/hello-world/hello.pipeline.yaml +2 -2
- package/examples/mcp-hitl-tour/{review.yaml → mcp-hitl-review.yaml} +1 -1
- package/examples/mcp-hitl-tour/mcp-hitl-tour.pipeline.yaml +3 -3
- package/examples/oss-issue-contribution/oss-explain-fix.yaml +1 -0
- package/examples/oss-issue-contribution/oss-explain-issue.yaml +1 -0
- package/examples/oss-issue-contribution/oss-issue-contribution.pipeline.yaml +0 -2
- package/examples/stageflow.yaml +6 -0
- package/examples/triggers/sample-github-pr.trigger.yaml +12 -0
- package/examples/triggers/sample-inbox-email.trigger.yaml +14 -0
- package/examples/triggers/sample-manual-hello.trigger.yaml +5 -0
- package/examples/triggers/sample-nightly-hello.trigger.yaml +8 -0
- package/examples/triggers/sample-signed-webhook.trigger.yaml +11 -0
- package/examples/triggers-readiness/README.md +48 -0
- package/examples/triggers-readiness/readiness-emit.yaml +18 -0
- package/examples/triggers-readiness/readiness.pipeline.yaml +4 -0
- package/examples/triggers-readiness/readiness.task.yaml +6 -0
- package/examples/triggers-readiness/stageflow.yaml +13 -0
- package/examples/triggers-readiness/triggers/readiness-dynamic-manual.trigger.yaml +4 -0
- package/examples/triggers-readiness/triggers/readiness-email.trigger.yaml +12 -0
- package/examples/triggers-readiness/triggers/readiness-github-pr.trigger.yaml +12 -0
- package/examples/triggers-readiness/triggers/readiness-manual.trigger.yaml +5 -0
- package/examples/triggers-readiness/triggers/readiness-schedule.trigger.yaml +8 -0
- package/examples/triggers-readiness/triggers/readiness-webhook.trigger.yaml +11 -0
- package/package.json +9 -1
- package/skills/stageflow/references/control-surface.md +1 -1
- package/skills/stageflow-author/references/catalog-write-conventions.md +2 -2
- package/skills/stageflow-run/SKILL.md +1 -1
- package/skills/stageflow-run/references/mcp-call.md +1 -1
- package/skills/stageflow-setup/SKILL.md +1 -1
- package/dist/ui/assets/index-59cjF0OA.js +0 -133
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import path from "node:path";
|
|
1
2
|
import { parse as parseYaml } from "yaml";
|
|
3
|
+
import { CatalogPathError, resolveDefaultWriteRoot, } from "../../config/catalogRelativePath.js";
|
|
2
4
|
import { defaultWorkshopPackageDirectory } from "../../config/ensureCatalogScanRoot.js";
|
|
3
5
|
import { publishDraftPackage } from "../../config/publishDraftPackage.js";
|
|
6
|
+
import { globalStageflowHome } from "../../project/globalHome.js";
|
|
4
7
|
import { emptyDraftPackage, isWorkshopDraftContext, readDraftFromContext, withDraft, } from "../draftContext.js";
|
|
5
8
|
import { focusUnboundWorkshopBuild, getWorkshopBuild, listWorkshopPickerRows, resolvePickerCatalogPipelines, } from "../../workshop/buildStore.js";
|
|
6
9
|
import { focusWorkshopBuildPointer, pinWorkshopBuildOnCreate, recordPinnedWorkshopSave, resolveLiveWorkshopBinding, resolvePinnedSaveDestination, } from "../../workshop/workshopPin.js";
|
|
@@ -99,10 +102,10 @@ function readWorkshopContext(ctx) {
|
|
|
99
102
|
return raw;
|
|
100
103
|
return { draft: readDraftFromContext(raw) };
|
|
101
104
|
}
|
|
102
|
-
function resolveDestination(ctx, args) {
|
|
105
|
+
function resolveDestination(ctx, args, catalogRootKind) {
|
|
103
106
|
const directory = stringArg(args, "directory") ??
|
|
104
107
|
readWorkshopContext(ctx).destination?.directory ??
|
|
105
|
-
defaultWorkshopPackageDirectory(readDraftFromContext(ctx.getContext()).pipeline.id);
|
|
108
|
+
defaultWorkshopPackageDirectory(readDraftFromContext(ctx.getContext()).pipeline.id, catalogRootKind);
|
|
106
109
|
const pipelineFilename = stringArg(args, "pipelineFilename") ??
|
|
107
110
|
stringArg(args, "pipeline_filename") ??
|
|
108
111
|
readWorkshopContext(ctx).destination?.pipelineFilename;
|
|
@@ -113,6 +116,64 @@ function resolveProjectRoot(ctx, defaultProjectRoot) {
|
|
|
113
116
|
// (or the profile/host default passed into createSaveTool).
|
|
114
117
|
return readWorkshopContext(ctx).projectRoot ?? defaultProjectRoot ?? null;
|
|
115
118
|
}
|
|
119
|
+
async function resolveSaveWriteTarget(ctx, options) {
|
|
120
|
+
const bound = resolveProjectRoot(ctx, options.projectRoot);
|
|
121
|
+
const live = liveWorkshopBinding(ctx);
|
|
122
|
+
const storeRoot = live?.storeRoot ?? globalStageflowHome();
|
|
123
|
+
const { createRunStore } = await import("../../runstore/createStore.js");
|
|
124
|
+
const store = createRunStore({ rootDir: storeRoot });
|
|
125
|
+
try {
|
|
126
|
+
if (bound) {
|
|
127
|
+
try {
|
|
128
|
+
const { wireRoot } = await resolveDefaultWriteRoot({ store }, bound);
|
|
129
|
+
return {
|
|
130
|
+
ok: true,
|
|
131
|
+
target: {
|
|
132
|
+
fsRoot: wireRoot.path,
|
|
133
|
+
wireProjectRoot: wireRoot.project_root,
|
|
134
|
+
catalogRootKind: wireRoot.kind,
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
catch (err) {
|
|
139
|
+
if (err instanceof CatalogPathError &&
|
|
140
|
+
err.code === "unknown_project_root") {
|
|
141
|
+
const abs = path.resolve(bound);
|
|
142
|
+
return {
|
|
143
|
+
ok: true,
|
|
144
|
+
target: {
|
|
145
|
+
fsRoot: abs,
|
|
146
|
+
wireProjectRoot: abs,
|
|
147
|
+
catalogRootKind: "registered",
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
if (err instanceof CatalogPathError) {
|
|
152
|
+
return { ok: false, error: err.message };
|
|
153
|
+
}
|
|
154
|
+
throw err;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
const { wireRoot } = await resolveDefaultWriteRoot({ store }, undefined);
|
|
158
|
+
return {
|
|
159
|
+
ok: true,
|
|
160
|
+
target: {
|
|
161
|
+
fsRoot: wireRoot.path,
|
|
162
|
+
wireProjectRoot: wireRoot.project_root,
|
|
163
|
+
catalogRootKind: wireRoot.kind,
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
catch (err) {
|
|
168
|
+
if (err instanceof CatalogPathError) {
|
|
169
|
+
return { ok: false, error: err.message };
|
|
170
|
+
}
|
|
171
|
+
throw err;
|
|
172
|
+
}
|
|
173
|
+
finally {
|
|
174
|
+
await store.close();
|
|
175
|
+
}
|
|
176
|
+
}
|
|
116
177
|
export function buildCreateStageDraft(draft, args) {
|
|
117
178
|
const existingIds = new Set(draft.pipeline.stages.map((s) => (typeof s.id === "string" ? s.id : "")));
|
|
118
179
|
let stageId = stringArg(args, "id") ??
|
|
@@ -366,7 +427,7 @@ async function listPickerCatalog(storeRoot) {
|
|
|
366
427
|
export function createWorkshopBuildTools() {
|
|
367
428
|
const listBuildsTool = {
|
|
368
429
|
name: "list_builds",
|
|
369
|
-
description: "List the same workshop rows as the studio picker (open builds and unbound disk pipelines). Does not create a build. Works when no build is focused.",
|
|
430
|
+
description: "List the same workshop rows as the studio picker (open builds and unbound disk pipelines). Each row includes catalogListed (whether Tasks/Pipelines would list that pipeline path). Does not create a build. Works when no build is focused.",
|
|
370
431
|
async handler(_args, ctx) {
|
|
371
432
|
const live = liveWorkshopBinding(ctx);
|
|
372
433
|
if (!live) {
|
|
@@ -374,7 +435,16 @@ export function createWorkshopBuildTools() {
|
|
|
374
435
|
}
|
|
375
436
|
try {
|
|
376
437
|
const catalog = await listPickerCatalog(live.storeRoot);
|
|
377
|
-
const rows = listWorkshopPickerRows(live.storeRoot, catalog.pipelines, catalog.roots)
|
|
438
|
+
const rows = listWorkshopPickerRows(live.storeRoot, catalog.pipelines, catalog.roots).map((row) => {
|
|
439
|
+
if (!row.projectRoot || !row.relativePath) {
|
|
440
|
+
return { ...row, catalogListed: false };
|
|
441
|
+
}
|
|
442
|
+
const relPath = row.relativePath;
|
|
443
|
+
const normalize = (value) => value.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
444
|
+
const listed = catalog.pipelines.some((pipeline) => pipeline.project_root === row.projectRoot &&
|
|
445
|
+
normalize(pipeline.path) === normalize(relPath));
|
|
446
|
+
return { ...row, catalogListed: listed };
|
|
447
|
+
});
|
|
378
448
|
return { ok: true, content: { rows } };
|
|
379
449
|
}
|
|
380
450
|
catch (err) {
|
|
@@ -556,23 +626,24 @@ export function createWorkshopAuthorMutatingTools() {
|
|
|
556
626
|
export function createSaveTool(options = {}) {
|
|
557
627
|
return {
|
|
558
628
|
name: "save",
|
|
559
|
-
description: "Validate-then-write the draft via catalog facades (createDraftPackage / overwriteDraftPackage). When directory is omitted, writes under workshop/<pipeline-id
|
|
629
|
+
description: "Validate-then-write the draft via catalog facades (createDraftPackage / overwriteDraftPackage). When directory is omitted, writes under workshop/<pipeline-id> on registered catalogs (or <pipeline-id> on the workspace catalog). The host adds registered workshop paths to stageflow.yaml so Run can see them. Pass directory only when the operator names a folder. Soft undo does not reverse disk. Prefer mode auto; set allowInvalid only when the operator explicitly requests saving invalid YAML. Do not pass projectRoot — the host binds it.",
|
|
560
630
|
async handler(args, ctx) {
|
|
561
|
-
const
|
|
562
|
-
|
|
563
|
-
if (!destination) {
|
|
631
|
+
const writeTarget = await resolveSaveWriteTarget(ctx, options);
|
|
632
|
+
if (!writeTarget.ok) {
|
|
564
633
|
return {
|
|
565
634
|
ok: false,
|
|
566
635
|
content: null,
|
|
567
|
-
error:
|
|
636
|
+
error: writeTarget.error,
|
|
568
637
|
};
|
|
569
638
|
}
|
|
570
|
-
const
|
|
571
|
-
|
|
639
|
+
const { fsRoot, catalogRootKind, wireProjectRoot } = writeTarget.target;
|
|
640
|
+
const pinnedDestination = resolvePinnedSaveDestination(ctx.getContext(), fsRoot);
|
|
641
|
+
const destination = pinnedDestination ?? resolveDestination(ctx, args, catalogRootKind);
|
|
642
|
+
if (!destination) {
|
|
572
643
|
return {
|
|
573
644
|
ok: false,
|
|
574
645
|
content: null,
|
|
575
|
-
error: "
|
|
646
|
+
error: "destination is required — set context.destination or pass directory (do not invent a disk path)",
|
|
576
647
|
};
|
|
577
648
|
}
|
|
578
649
|
const draft = readDraftFromContext(ctx.getContext());
|
|
@@ -589,7 +660,9 @@ export function createSaveTool(options = {}) {
|
|
|
589
660
|
: {}),
|
|
590
661
|
...(allowInvalid ? { allowInvalid: true } : {}),
|
|
591
662
|
};
|
|
592
|
-
const published = await publishDraftPackage(
|
|
663
|
+
const published = await publishDraftPackage(fsRoot, input, mode, {
|
|
664
|
+
catalogRootKind,
|
|
665
|
+
});
|
|
593
666
|
const result = published.write;
|
|
594
667
|
if (result.ok) {
|
|
595
668
|
const current = readWorkshopContext(ctx);
|
|
@@ -602,20 +675,34 @@ export function createSaveTool(options = {}) {
|
|
|
602
675
|
? { pipelineFilename: destination.pipelineFilename }
|
|
603
676
|
: {}),
|
|
604
677
|
},
|
|
605
|
-
projectRoot,
|
|
678
|
+
projectRoot: fsRoot,
|
|
606
679
|
});
|
|
607
680
|
recordPinnedWorkshopSave(ctx.getContext(), {
|
|
608
681
|
directory: destination.directory,
|
|
609
682
|
...(destination.pipelineFilename
|
|
610
683
|
? { pipelineFilename: destination.pipelineFilename }
|
|
611
684
|
: {}),
|
|
612
|
-
projectRoot,
|
|
685
|
+
projectRoot: fsRoot,
|
|
613
686
|
draft,
|
|
687
|
+
relativePath: result.pipelinePath,
|
|
614
688
|
});
|
|
615
689
|
}
|
|
616
690
|
return {
|
|
617
691
|
ok: result.ok,
|
|
618
|
-
content: result
|
|
692
|
+
content: result.ok
|
|
693
|
+
? {
|
|
694
|
+
...result,
|
|
695
|
+
published: {
|
|
696
|
+
project_root: wireProjectRoot,
|
|
697
|
+
project_root_path: fsRoot,
|
|
698
|
+
pipeline_path: result.pipelinePath,
|
|
699
|
+
stage_paths: result.stagePaths,
|
|
700
|
+
...(result.taskPath !== undefined
|
|
701
|
+
? { task_path: result.taskPath }
|
|
702
|
+
: { task_path: null }),
|
|
703
|
+
},
|
|
704
|
+
}
|
|
705
|
+
: result,
|
|
619
706
|
...(result.ok ? {} : { error: result.error }),
|
|
620
707
|
};
|
|
621
708
|
},
|
package/dist/package-meta.d.ts
CHANGED
package/dist/package-meta.js
CHANGED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
export function parseEnsureProjectRootsEnv(env) {
|
|
3
|
+
const raw = env.STAGEFLOW_ENSURE_PROJECT_ROOTS?.trim();
|
|
4
|
+
if (!raw)
|
|
5
|
+
return [];
|
|
6
|
+
return raw
|
|
7
|
+
.split(",")
|
|
8
|
+
.map((entry) => entry.trim())
|
|
9
|
+
.filter((entry) => entry.length > 0);
|
|
10
|
+
}
|
|
11
|
+
export async function ensureProjectRootsFromEnv(env, store) {
|
|
12
|
+
for (const entry of parseEnsureProjectRootsEnv(env)) {
|
|
13
|
+
const abs = path.resolve(entry);
|
|
14
|
+
try {
|
|
15
|
+
await store.ensureProject(abs);
|
|
16
|
+
}
|
|
17
|
+
catch (err) {
|
|
18
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
19
|
+
console.warn(`stageflow: could not register project_root ${abs}: ${message}`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -5,5 +5,6 @@ export declare class StageflowHomeError extends Error {
|
|
|
5
5
|
}
|
|
6
6
|
export declare function resetGlobalStageflowHomeForTests(): void;
|
|
7
7
|
export declare function globalStageflowHome(): string;
|
|
8
|
+
export declare function globalCredentialRoot(): string;
|
|
8
9
|
export declare function assertStageflowHomeWritable(): void;
|
|
9
10
|
export declare function ensureGlobalHome(): string;
|
|
@@ -10,8 +10,10 @@ export class StageflowHomeError extends Error {
|
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
let memoizedHome;
|
|
13
|
+
let memoizedCredentialRoot;
|
|
13
14
|
export function resetGlobalStageflowHomeForTests() {
|
|
14
15
|
memoizedHome = undefined;
|
|
16
|
+
memoizedCredentialRoot = undefined;
|
|
15
17
|
}
|
|
16
18
|
function resolveStageflowHomeFromEnv() {
|
|
17
19
|
const raw = process.env.STAGEFLOW_HOME?.trim();
|
|
@@ -30,6 +32,22 @@ export function globalStageflowHome() {
|
|
|
30
32
|
}
|
|
31
33
|
return memoizedHome;
|
|
32
34
|
}
|
|
35
|
+
function resolveCredentialRootFromEnv() {
|
|
36
|
+
const raw = process.env.STAGEFLOW_CREDENTIAL_HOME?.trim();
|
|
37
|
+
if (raw) {
|
|
38
|
+
if (path.isAbsolute(raw)) {
|
|
39
|
+
return path.resolve(raw);
|
|
40
|
+
}
|
|
41
|
+
return path.resolve(process.cwd(), raw);
|
|
42
|
+
}
|
|
43
|
+
return path.join(os.homedir(), ".stageflow");
|
|
44
|
+
}
|
|
45
|
+
export function globalCredentialRoot() {
|
|
46
|
+
if (memoizedCredentialRoot === undefined) {
|
|
47
|
+
memoizedCredentialRoot = resolveCredentialRootFromEnv();
|
|
48
|
+
}
|
|
49
|
+
return memoizedCredentialRoot;
|
|
50
|
+
}
|
|
33
51
|
function stageflowHomeNotWritableMessage(resolvedPath) {
|
|
34
52
|
const uid = process.getuid?.() ?? 0;
|
|
35
53
|
const gid = process.getgid?.() ?? 0;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const WORKSPACE_CATALOG_ID = "workspace";
|
|
2
|
+
export type WorkspaceProvisionResult = {
|
|
3
|
+
path: string;
|
|
4
|
+
ok: boolean;
|
|
5
|
+
reason?: string;
|
|
6
|
+
};
|
|
7
|
+
export declare function resetWorkspaceProvisionForTests(): void;
|
|
8
|
+
export declare function lastWorkspaceProvisionResult(): WorkspaceProvisionResult | undefined;
|
|
9
|
+
export declare function workspaceCatalogPath(home?: string): string;
|
|
10
|
+
export declare function ensureWorkspaceCatalog(home?: string): WorkspaceProvisionResult;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { accessSync, constants, mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { globalStageflowHome } from "./globalHome.js";
|
|
4
|
+
export const WORKSPACE_CATALOG_ID = "workspace";
|
|
5
|
+
let lastProvisionResult;
|
|
6
|
+
export function resetWorkspaceProvisionForTests() {
|
|
7
|
+
lastProvisionResult = undefined;
|
|
8
|
+
}
|
|
9
|
+
export function lastWorkspaceProvisionResult() {
|
|
10
|
+
return lastProvisionResult;
|
|
11
|
+
}
|
|
12
|
+
export function workspaceCatalogPath(home) {
|
|
13
|
+
return path.join(home ?? globalStageflowHome(), "workspace");
|
|
14
|
+
}
|
|
15
|
+
function workspaceManifestYaml() {
|
|
16
|
+
return `version: 1
|
|
17
|
+
catalog:
|
|
18
|
+
pipelines:
|
|
19
|
+
- .
|
|
20
|
+
tasks:
|
|
21
|
+
- .
|
|
22
|
+
triggers:
|
|
23
|
+
- .
|
|
24
|
+
patterns:
|
|
25
|
+
pipeline: "*.pipeline.yaml"
|
|
26
|
+
task: "*.task.yaml"
|
|
27
|
+
trigger: "*.trigger.yaml"
|
|
28
|
+
`;
|
|
29
|
+
}
|
|
30
|
+
function workspaceNotWritableReason(resolvedPath) {
|
|
31
|
+
const uid = process.getuid?.() ?? 0;
|
|
32
|
+
const gid = process.getgid?.() ?? 0;
|
|
33
|
+
return `Workspace catalog is not writable (${resolvedPath}). Running as uid=${uid} gid=${gid}. Try: sudo chown -R ${uid}:${gid} ${path.dirname(resolvedPath)}`;
|
|
34
|
+
}
|
|
35
|
+
function isWritableDir(dir) {
|
|
36
|
+
try {
|
|
37
|
+
accessSync(dir, constants.W_OK);
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
const code = err.code;
|
|
42
|
+
if (code === "ENOENT") {
|
|
43
|
+
const parent = path.dirname(dir);
|
|
44
|
+
if (parent === dir)
|
|
45
|
+
return false;
|
|
46
|
+
try {
|
|
47
|
+
accessSync(parent, constants.W_OK);
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
export function ensureWorkspaceCatalog(home) {
|
|
58
|
+
const wsPath = workspaceCatalogPath(home);
|
|
59
|
+
if (!isWritableDir(wsPath)) {
|
|
60
|
+
const result = {
|
|
61
|
+
path: wsPath,
|
|
62
|
+
ok: false,
|
|
63
|
+
reason: workspaceNotWritableReason(wsPath),
|
|
64
|
+
};
|
|
65
|
+
lastProvisionResult = result;
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
mkdirSync(wsPath, { recursive: true });
|
|
70
|
+
const manifestPath = path.join(wsPath, "stageflow.yaml");
|
|
71
|
+
try {
|
|
72
|
+
accessSync(manifestPath, constants.F_OK);
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
writeFileSync(manifestPath, workspaceManifestYaml(), "utf8");
|
|
76
|
+
}
|
|
77
|
+
const result = { path: wsPath, ok: true };
|
|
78
|
+
lastProvisionResult = result;
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
catch (err) {
|
|
82
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
83
|
+
const result = {
|
|
84
|
+
path: wsPath,
|
|
85
|
+
ok: false,
|
|
86
|
+
reason: `${workspaceNotWritableReason(wsPath)} (${message})`,
|
|
87
|
+
};
|
|
88
|
+
lastProvisionResult = result;
|
|
89
|
+
return result;
|
|
90
|
+
}
|
|
91
|
+
}
|
package/dist/runstore/backup.js
CHANGED
|
@@ -8,7 +8,8 @@ import { pipeline } from "node:stream/promises";
|
|
|
8
8
|
import { createWriteStream } from "node:fs";
|
|
9
9
|
import Database from "better-sqlite3";
|
|
10
10
|
import { PACKAGE_VERSION } from "../package-meta.js";
|
|
11
|
-
import { globalStageflowHome } from "../project/globalHome.js";
|
|
11
|
+
import { globalCredentialRoot, globalStageflowHome } from "../project/globalHome.js";
|
|
12
|
+
import { isUsableAuthFile } from "../runtime/credentialBinding.js";
|
|
12
13
|
import { readFilesystemSize } from "./diskUsage.js";
|
|
13
14
|
import { isInsideDir } from "./workspaceLayout.js";
|
|
14
15
|
export class BackupError extends Error {
|
|
@@ -45,6 +46,14 @@ export function assertBackupOutPathAllowed(outPath, homeDir = globalStageflowHom
|
|
|
45
46
|
}
|
|
46
47
|
return resolved;
|
|
47
48
|
}
|
|
49
|
+
function isCredentialRootDir(dir) {
|
|
50
|
+
return path.resolve(dir) === path.resolve(globalCredentialRoot());
|
|
51
|
+
}
|
|
52
|
+
function packAuthMember(homeDir, authPath, noCredentials) {
|
|
53
|
+
return (!noCredentials &&
|
|
54
|
+
isCredentialRootDir(homeDir) &&
|
|
55
|
+
isUsableAuthFile(authPath));
|
|
56
|
+
}
|
|
48
57
|
function fingerprint(filePath) {
|
|
49
58
|
if (!existsSync(filePath))
|
|
50
59
|
return null;
|
|
@@ -203,7 +212,8 @@ export async function createBackup(options) {
|
|
|
203
212
|
});
|
|
204
213
|
contents.push("settings.json");
|
|
205
214
|
}
|
|
206
|
-
|
|
215
|
+
const includeAuth = packAuthMember(homeDir, authPath, noCredentials);
|
|
216
|
+
if (includeAuth) {
|
|
207
217
|
const stagedAuth = path.join(staging, "auth.json");
|
|
208
218
|
copyFileSync(authPath, stagedAuth);
|
|
209
219
|
chmodSync(stagedAuth, 0o600);
|
|
@@ -226,14 +236,14 @@ export async function createBackup(options) {
|
|
|
226
236
|
schema_version: userVersion,
|
|
227
237
|
contents,
|
|
228
238
|
db_only: false,
|
|
229
|
-
credentials_included:
|
|
239
|
+
credentials_included: includeAuth,
|
|
230
240
|
a2a_artifacts_included: includeA2a,
|
|
231
241
|
settings_fingerprint_before: settingsBefore,
|
|
232
242
|
settings_fingerprint_after: settingsAfter,
|
|
233
243
|
auth_fingerprint_before: authBefore,
|
|
234
244
|
auth_fingerprint_after: authAfter,
|
|
235
245
|
fingerprint_skew: fingerprintSkew,
|
|
236
|
-
secret_warning: SECRET_WARNING,
|
|
246
|
+
secret_warning: includeAuth ? SECRET_WARNING : "",
|
|
237
247
|
};
|
|
238
248
|
const manifestPath = path.join(staging, "manifest.json");
|
|
239
249
|
writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`, {
|
package/dist/runstore/port.d.ts
CHANGED
|
@@ -99,6 +99,7 @@ export type StageSnapshot = {
|
|
|
99
99
|
attempt_count: number;
|
|
100
100
|
/** Total $ spent on this stage across every attempt; omitted when no attempt reported usage. */
|
|
101
101
|
cost_usd?: number;
|
|
102
|
+
usage?: StageUsage;
|
|
102
103
|
};
|
|
103
104
|
export type StageExecution = {
|
|
104
105
|
run_id: string;
|
|
@@ -470,12 +471,21 @@ export interface RunStore {
|
|
|
470
471
|
upsertTrigger(input: UpsertTriggerInput): Promise<TriggerRecord>;
|
|
471
472
|
getTrigger(id: string): Promise<TriggerRecord | null>;
|
|
472
473
|
listTriggers(): Promise<TriggerRecord[]>;
|
|
473
|
-
/** Record a fire: stamps last_fired_at/last_run_id. Throws if the trigger is missing. */
|
|
474
|
+
/** Record a fire: stamps last_fired_at/last_run_id and appends trigger_fires. Throws if the trigger is missing. */
|
|
474
475
|
recordTriggerFired(id: string, runId: string): Promise<void>;
|
|
476
|
+
/** Newest first. */
|
|
477
|
+
listTriggerFires(triggerId: string, limit: number): Promise<Array<{
|
|
478
|
+
fired_at: string;
|
|
479
|
+
run_id: string;
|
|
480
|
+
}>>;
|
|
475
481
|
/** Persist the next computed fire time for a schedule-kind trigger. Throws if the trigger is missing. */
|
|
476
482
|
setTriggerNextRun(id: string, nextRunAt: string): Promise<void>;
|
|
477
483
|
/** Read a single adapter-owned state value for a trigger, or null if unset. */
|
|
478
484
|
getTriggerAdapterState(triggerId: string, key: string): Promise<string | null>;
|
|
485
|
+
getTriggerAdapterStateMeta(triggerId: string, key: string): Promise<{
|
|
486
|
+
value: string;
|
|
487
|
+
updated_at: string;
|
|
488
|
+
} | null>;
|
|
479
489
|
/** Upsert a single adapter-owned state value for a trigger. */
|
|
480
490
|
setTriggerAdapterState(triggerId: string, key: string, value: string): Promise<void>;
|
|
481
491
|
readRun(runId: string): Promise<RunDetail>;
|
package/dist/runstore/restore.js
CHANGED
|
@@ -7,7 +7,8 @@ import { pipeline } from "node:stream/promises";
|
|
|
7
7
|
import { createWriteStream } from "node:fs";
|
|
8
8
|
import Database from "better-sqlite3";
|
|
9
9
|
import { PACKAGE_VERSION } from "../package-meta.js";
|
|
10
|
-
import { globalStageflowHome } from "../project/globalHome.js";
|
|
10
|
+
import { globalCredentialRoot, globalStageflowHome } from "../project/globalHome.js";
|
|
11
|
+
import { isUsableAuthFile } from "../runtime/credentialBinding.js";
|
|
11
12
|
import { CURRENT_SCHEMA_VERSION } from "./sqlite/migrations/index.js";
|
|
12
13
|
import { StoreSchemaError } from "./sqlite/storeSchemaError.js";
|
|
13
14
|
import { assertStoreQuickCheck } from "./sqlite/applyStorePragmas.js";
|
|
@@ -234,7 +235,9 @@ export async function applyRestoreArchive(options) {
|
|
|
234
235
|
if (existsSync(settingsSrc)) {
|
|
235
236
|
copyFileSync(settingsSrc, path.join(homeDir, "settings.json"));
|
|
236
237
|
}
|
|
237
|
-
|
|
238
|
+
const restoreAuth = path.resolve(homeDir) === path.resolve(globalCredentialRoot()) &&
|
|
239
|
+
isUsableAuthFile(authSrc);
|
|
240
|
+
if (restoreAuth) {
|
|
238
241
|
const agentDir = path.join(homeDir, "agent");
|
|
239
242
|
mkdirSync(agentDir, { recursive: true });
|
|
240
243
|
try {
|
|
@@ -82,8 +82,16 @@ export declare class SqliteRunStore implements RunStore {
|
|
|
82
82
|
getTrigger(id: string): Promise<TriggerRecord | null>;
|
|
83
83
|
listTriggers(): Promise<TriggerRecord[]>;
|
|
84
84
|
recordTriggerFired(id: string, runId: string): Promise<void>;
|
|
85
|
+
listTriggerFires(triggerId: string, limit: number): Promise<Array<{
|
|
86
|
+
fired_at: string;
|
|
87
|
+
run_id: string;
|
|
88
|
+
}>>;
|
|
85
89
|
setTriggerNextRun(id: string, nextRunAt: string): Promise<void>;
|
|
86
90
|
getTriggerAdapterState(triggerId: string, key: string): Promise<string | null>;
|
|
91
|
+
getTriggerAdapterStateMeta(triggerId: string, key: string): Promise<{
|
|
92
|
+
value: string;
|
|
93
|
+
updated_at: string;
|
|
94
|
+
} | null>;
|
|
87
95
|
setTriggerAdapterState(triggerId: string, key: string, value: string): Promise<void>;
|
|
88
96
|
readRun(runId: string): Promise<RunDetail>;
|
|
89
97
|
createFeedbackLoop(runId: string, input: CreateFeedbackLoopInput): Promise<FeedbackLoopRecord>;
|
|
@@ -942,13 +942,29 @@ export class SqliteRunStore {
|
|
|
942
942
|
async recordTriggerFired(id, runId) {
|
|
943
943
|
await this.ready();
|
|
944
944
|
const now = new Date().toISOString();
|
|
945
|
-
const
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
945
|
+
const apply = this.db.transaction(() => {
|
|
946
|
+
const result = this.db
|
|
947
|
+
.prepare(`UPDATE triggers SET last_fired_at = @last_fired_at, last_run_id = @last_run_id, updated_at = @updated_at
|
|
948
|
+
WHERE id = @id`)
|
|
949
|
+
.run({ id, last_fired_at: now, last_run_id: runId, updated_at: now });
|
|
950
|
+
if (result.changes === 0) {
|
|
951
|
+
throw new Error(`Trigger not found: ${id}`);
|
|
952
|
+
}
|
|
953
|
+
this.db
|
|
954
|
+
.prepare(`INSERT INTO trigger_fires (trigger_id, run_id, fired_at)
|
|
955
|
+
VALUES (@trigger_id, @run_id, @fired_at)`)
|
|
956
|
+
.run({ trigger_id: id, run_id: runId, fired_at: now });
|
|
957
|
+
});
|
|
958
|
+
apply();
|
|
959
|
+
}
|
|
960
|
+
async listTriggerFires(triggerId, limit) {
|
|
961
|
+
await this.ready();
|
|
962
|
+
return this.db
|
|
963
|
+
.prepare(`SELECT fired_at, run_id FROM trigger_fires
|
|
964
|
+
WHERE trigger_id = ?
|
|
965
|
+
ORDER BY fired_at DESC, id DESC
|
|
966
|
+
LIMIT ?`)
|
|
967
|
+
.all(triggerId, limit);
|
|
952
968
|
}
|
|
953
969
|
async setTriggerNextRun(id, nextRunAt) {
|
|
954
970
|
await this.ready();
|
|
@@ -962,11 +978,15 @@ export class SqliteRunStore {
|
|
|
962
978
|
}
|
|
963
979
|
}
|
|
964
980
|
async getTriggerAdapterState(triggerId, key) {
|
|
981
|
+
const row = await this.getTriggerAdapterStateMeta(triggerId, key);
|
|
982
|
+
return row?.value ?? null;
|
|
983
|
+
}
|
|
984
|
+
async getTriggerAdapterStateMeta(triggerId, key) {
|
|
965
985
|
await this.ready();
|
|
966
986
|
const row = this.db
|
|
967
|
-
.prepare(`SELECT value FROM trigger_adapter_state WHERE trigger_id = ? AND key = ?`)
|
|
987
|
+
.prepare(`SELECT value, updated_at FROM trigger_adapter_state WHERE trigger_id = ? AND key = ?`)
|
|
968
988
|
.get(triggerId, key);
|
|
969
|
-
return row
|
|
989
|
+
return row ?? null;
|
|
970
990
|
}
|
|
971
991
|
async setTriggerAdapterState(triggerId, key, value) {
|
|
972
992
|
await this.ready();
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { PACKAGE_VERSION } from "../../../package-meta.js";
|
|
2
|
+
export const MIGRATION_012 = {
|
|
3
|
+
version: 12,
|
|
4
|
+
name: "012_trigger_fires",
|
|
5
|
+
minStageflowVersion: PACKAGE_VERSION,
|
|
6
|
+
up(db) {
|
|
7
|
+
db.exec(`
|
|
8
|
+
CREATE TABLE IF NOT EXISTS trigger_fires (
|
|
9
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
10
|
+
trigger_id TEXT NOT NULL,
|
|
11
|
+
run_id TEXT NOT NULL,
|
|
12
|
+
fired_at TEXT NOT NULL
|
|
13
|
+
);
|
|
14
|
+
CREATE INDEX IF NOT EXISTS trigger_fires_trigger_fired
|
|
15
|
+
ON trigger_fires (trigger_id, fired_at DESC);
|
|
16
|
+
`);
|
|
17
|
+
},
|
|
18
|
+
};
|
|
@@ -10,6 +10,7 @@ import { MIGRATION_008 } from "./008-triggers-table.js";
|
|
|
10
10
|
import { MIGRATION_009 } from "./009-trigger-next-run.js";
|
|
11
11
|
import { MIGRATION_010 } from "./010-trigger-adapter-state.js";
|
|
12
12
|
import { MIGRATION_011 } from "./011-email-dispatch-key.js";
|
|
13
|
+
import { MIGRATION_012 } from "./012-trigger-fires.js";
|
|
13
14
|
const DEFAULT_MIGRATIONS = [
|
|
14
15
|
MIGRATION_001,
|
|
15
16
|
MIGRATION_002,
|
|
@@ -22,6 +23,7 @@ const DEFAULT_MIGRATIONS = [
|
|
|
22
23
|
MIGRATION_009,
|
|
23
24
|
MIGRATION_010,
|
|
24
25
|
MIGRATION_011,
|
|
26
|
+
MIGRATION_012,
|
|
25
27
|
];
|
|
26
28
|
export const CURRENT_SCHEMA_VERSION = DEFAULT_MIGRATIONS[DEFAULT_MIGRATIONS.length - 1].version;
|
|
27
29
|
function throwStoreSchemaTooNew(db, version, maxKnown) {
|
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { type StageUsage } from "../types/usage.js";
|
|
2
|
+
import type { RunStore, StageExecution, StageSnapshot } from "./port.js";
|
|
2
3
|
export declare function buildStageSnapshotFromStore(store: RunStore, runId: string, stageId: string, workspaceDir: string): Promise<StageSnapshot>;
|
|
4
|
+
export declare function mergeStageExecutionUsage(executions: StageExecution[]): StageUsage | undefined;
|