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.
Files changed (335) hide show
  1. package/README.md +4 -3
  2. package/dist/agent/adapterSpill.d.ts +14 -0
  3. package/dist/agent/adapterSpill.js +83 -0
  4. package/dist/agent/agentBackend.d.ts +2 -2
  5. package/dist/agent/agentBackend.js +2 -2
  6. package/dist/agent/claudeAdapter.d.ts +13 -2
  7. package/dist/agent/claudeAdapter.js +50 -6
  8. package/dist/agent/cursorProvider.d.ts +3 -0
  9. package/dist/agent/cursorProvider.js +23 -6
  10. package/dist/agent/fakeAgent.d.ts +3 -3
  11. package/dist/agent/fakeAgent.js +0 -6
  12. package/dist/agent/piAdapter.d.ts +2 -2
  13. package/dist/agent/piAdapter.js +116 -15
  14. package/dist/agent/piIsolatedMcp.d.ts +1 -0
  15. package/dist/agent/piIsolatedMcp.js +19 -1
  16. package/dist/agent/piIsolatedMcpProbe.d.ts +11 -0
  17. package/dist/agent/piIsolatedMcpProbe.js +20 -0
  18. package/dist/agent/port.d.ts +2 -2
  19. package/dist/agent/providerAuth.d.ts +6 -0
  20. package/dist/agent/providerAuth.js +86 -17
  21. package/dist/agent/{resolveAgentPort.d.ts → resolveStagePort.d.ts} +8 -6
  22. package/dist/agent/{resolveAgentPort.js → resolveStagePort.js} +13 -9
  23. package/dist/agent/stageTurnDriver.d.ts +33 -0
  24. package/dist/agent/stageTurnDriver.js +64 -0
  25. package/dist/agent/toolOutputBudget.d.ts +46 -0
  26. package/dist/agent/toolOutputBudget.js +97 -0
  27. package/dist/agent/toolOutputBudgetExtension.d.ts +22 -0
  28. package/dist/agent/toolOutputBudgetExtension.js +141 -0
  29. package/dist/agent/toolOutputSpill.d.ts +34 -0
  30. package/dist/agent/toolOutputSpill.js +85 -0
  31. package/dist/browser/agentBrowserLiveViewRelay.d.ts +41 -0
  32. package/dist/browser/agentBrowserLiveViewRelay.js +801 -0
  33. package/dist/browser/anchor.d.ts +2 -0
  34. package/dist/browser/anchor.js +2 -1
  35. package/dist/browser/auditSink.d.ts +8 -0
  36. package/dist/browser/browserHost.d.ts +29 -0
  37. package/dist/browser/browserSweep.d.ts +4 -1
  38. package/dist/browser/browserSweep.js +7 -0
  39. package/dist/browser/browserTeardown.d.ts +1 -0
  40. package/dist/browser/browserTeardown.js +32 -2
  41. package/dist/browser/containerBrowserEndpoint.d.ts +11 -0
  42. package/dist/browser/containerBrowserEndpoint.js +57 -0
  43. package/dist/browser/containerBrowserHost.d.ts +24 -0
  44. package/dist/browser/containerBrowserHost.js +147 -0
  45. package/dist/browser/dockerSandboxOrchestrator.d.ts +26 -0
  46. package/dist/browser/dockerSandboxOrchestrator.js +142 -0
  47. package/dist/browser/fakeLiveViewRelay.d.ts +15 -0
  48. package/dist/browser/fakeLiveViewRelay.js +94 -0
  49. package/dist/browser/fakeLiveViewSource.d.ts +6 -0
  50. package/dist/browser/fakeLiveViewSource.js +16 -0
  51. package/dist/browser/fakeRemoteBrowserHost.d.ts +2 -1
  52. package/dist/browser/fakeRemoteBrowserHost.js +2 -1
  53. package/dist/browser/fakeSandboxOrchestrator.d.ts +9 -0
  54. package/dist/browser/fakeSandboxOrchestrator.js +44 -0
  55. package/dist/browser/gateHandoff.d.ts +0 -2
  56. package/dist/browser/gateHandoff.js +5 -11
  57. package/dist/browser/hostCapabilities.d.ts +23 -0
  58. package/dist/browser/hostCapabilities.js +23 -0
  59. package/dist/browser/humanLogin.d.ts +2 -2
  60. package/dist/browser/humanLogin.js +11 -2
  61. package/dist/browser/liveViewPersisted.d.ts +11 -0
  62. package/dist/browser/liveViewPersisted.js +22 -0
  63. package/dist/browser/liveViewRelay.d.ts +76 -0
  64. package/dist/browser/liveViewRelay.js +1 -0
  65. package/dist/browser/liveViewSessions.d.ts +25 -0
  66. package/dist/browser/liveViewSessions.js +139 -0
  67. package/dist/browser/liveViewSource.d.ts +25 -0
  68. package/dist/browser/liveViewSource.js +7 -0
  69. package/dist/browser/liveViewTickets.d.ts +46 -0
  70. package/dist/browser/liveViewTickets.js +122 -0
  71. package/dist/browser/localBrowserHost.d.ts +10 -0
  72. package/dist/browser/localBrowserHost.js +53 -7
  73. package/dist/browser/ownerScope.d.ts +10 -0
  74. package/dist/browser/ownerScope.js +6 -0
  75. package/dist/browser/profileStore.d.ts +5 -2
  76. package/dist/browser/profileStore.js +3 -5
  77. package/dist/browser/sandboxOrchestrator.d.ts +60 -0
  78. package/dist/browser/sandboxOrchestrator.js +8 -0
  79. package/dist/browser/sessionApiSandboxOrchestrator.d.ts +34 -0
  80. package/dist/browser/sessionApiSandboxOrchestrator.js +108 -0
  81. package/dist/browser/stageBrowserEnv.d.ts +7 -0
  82. package/dist/browser/stageBrowserEnv.js +53 -15
  83. package/dist/browser/stageHandoff.d.ts +47 -0
  84. package/dist/browser/stageHandoff.js +101 -0
  85. package/dist/browser/stageProfileLock.d.ts +1 -0
  86. package/dist/browser/stageProfileLock.js +1 -3
  87. package/dist/browser/volumeProfileStore.d.ts +7 -0
  88. package/dist/browser/volumeProfileStore.js +35 -0
  89. package/dist/cli/browserCommand.d.ts +3 -1
  90. package/dist/cli/browserCommand.js +25 -20
  91. package/dist/cli/resolveCliProjectRoot.d.ts +7 -0
  92. package/dist/cli/resolveCliProjectRoot.js +27 -0
  93. package/dist/cli/runCommand.d.ts +1 -1
  94. package/dist/cli/runCommand.js +59 -17
  95. package/dist/cli/skillsCommand.d.ts +20 -0
  96. package/dist/cli/skillsCommand.js +74 -31
  97. package/dist/cli/validateCommand.d.ts +1 -1
  98. package/dist/cli/validateCommand.js +22 -4
  99. package/dist/cli.js +4 -4
  100. package/dist/config/browseCatalog.d.ts +2 -0
  101. package/dist/config/browseCatalog.js +6 -0
  102. package/dist/config/catalogRelativePath.d.ts +4 -0
  103. package/dist/config/catalogRelativePath.js +37 -9
  104. package/dist/config/createStage.d.ts +1 -0
  105. package/dist/config/createStage.js +11 -2
  106. package/dist/config/createTask.d.ts +30 -0
  107. package/dist/config/createTask.js +161 -0
  108. package/dist/config/createTrigger.d.ts +15 -0
  109. package/dist/config/createTrigger.js +32 -25
  110. package/dist/config/draftPackage.d.ts +41 -0
  111. package/dist/config/draftPackage.js +216 -23
  112. package/dist/config/ensureCatalogScanRoot.d.ts +2 -1
  113. package/dist/config/ensureCatalogScanRoot.js +6 -2
  114. package/dist/config/findTaskInCatalog.d.ts +33 -0
  115. package/dist/config/findTaskInCatalog.js +69 -0
  116. package/dist/config/hostConfig.d.ts +21 -0
  117. package/dist/config/hostConfig.js +113 -1
  118. package/dist/config/importTask.d.ts +19 -0
  119. package/dist/config/importTask.js +133 -0
  120. package/dist/config/installSkillRequest.d.ts +40 -0
  121. package/dist/config/installSkillRequest.js +286 -0
  122. package/dist/config/listConfig.d.ts +0 -16
  123. package/dist/config/listConfig.js +0 -3
  124. package/dist/config/loadOutcome.d.ts +11 -6
  125. package/dist/config/loadPipeline.js +0 -1
  126. package/dist/config/loadStage.js +2 -0
  127. package/dist/config/loadStageflowManifest.js +4 -1
  128. package/dist/config/loadTask.js +2 -0
  129. package/dist/config/loadTrigger.js +2 -0
  130. package/dist/config/mergePipelineIncludes.js +3 -0
  131. package/dist/config/normalizePipelineStageEntry.js +10 -1
  132. package/dist/config/printTargetYaml.js +0 -1
  133. package/dist/config/publishDraftPackage.d.ts +5 -1
  134. package/dist/config/publishDraftPackage.js +4 -1
  135. package/dist/config/resolveCatalogRoots.d.ts +4 -1
  136. package/dist/config/resolveCatalogRoots.js +18 -1
  137. package/dist/config/skillUsageIndex.d.ts +6 -0
  138. package/dist/config/skillUsageIndex.js +39 -0
  139. package/dist/config/stageBrowser.js +13 -0
  140. package/dist/config/triggerAdapterStatus.d.ts +11 -0
  141. package/dist/config/triggerAdapterStatus.js +90 -0
  142. package/dist/config/triggerCatalog.d.ts +41 -2
  143. package/dist/config/triggerCatalog.js +107 -15
  144. package/dist/config/updateTask.d.ts +30 -0
  145. package/dist/config/updateTask.js +119 -0
  146. package/dist/config/updateTrigger.d.ts +38 -0
  147. package/dist/config/updateTrigger.js +220 -0
  148. package/dist/config/validateCatalog.d.ts +6 -2
  149. package/dist/config/validateCatalog.js +48 -7
  150. package/dist/config/workshopCatalogFilenames.d.ts +37 -0
  151. package/dist/config/workshopCatalogFilenames.js +125 -0
  152. package/dist/config/workshopCatalogRepair.d.ts +7 -0
  153. package/dist/config/workshopCatalogRepair.js +144 -0
  154. package/dist/config/yamlParsePosition.d.ts +4 -0
  155. package/dist/config/yamlParsePosition.js +9 -0
  156. package/dist/hosted/containment.d.ts +3 -0
  157. package/dist/hosted/containment.js +36 -0
  158. package/dist/hosted/errors.d.ts +21 -0
  159. package/dist/hosted/errors.js +30 -0
  160. package/dist/hosted/packageSkills.d.ts +3 -0
  161. package/dist/hosted/packageSkills.js +80 -0
  162. package/dist/hosted/runtime.d.ts +12 -0
  163. package/dist/hosted/runtime.js +596 -0
  164. package/dist/hosted/sequencer.d.ts +28 -0
  165. package/dist/hosted/sequencer.js +129 -0
  166. package/dist/hosted/translate.d.ts +3 -0
  167. package/dist/hosted/translate.js +43 -0
  168. package/dist/hosted/types.d.ts +108 -0
  169. package/dist/hosted/types.js +10 -0
  170. package/dist/index.d.ts +9 -1
  171. package/dist/index.js +6 -0
  172. package/dist/mcp/getStartedTool.js +15 -6
  173. package/dist/mcp/triggerTools.js +2 -8
  174. package/dist/operatorAgent/agentPort.d.ts +11 -0
  175. package/dist/operatorAgent/agentPort.js +12 -0
  176. package/dist/operatorAgent/index.d.ts +1 -0
  177. package/dist/operatorAgent/index.js +1 -0
  178. package/dist/operatorAgent/piModel.js +26 -6
  179. package/dist/operatorAgent/profiles/workshopAuthorPlaybook.d.ts +1 -1
  180. package/dist/operatorAgent/profiles/workshopAuthorPlaybook.js +4 -2
  181. package/dist/operatorAgent/profiles/workshopAuthorTools.js +103 -16
  182. package/dist/package-meta.d.ts +1 -1
  183. package/dist/package-meta.js +1 -1
  184. package/dist/project/ensureProjectRootsFromEnv.d.ts +3 -0
  185. package/dist/project/ensureProjectRootsFromEnv.js +22 -0
  186. package/dist/project/globalHome.d.ts +1 -0
  187. package/dist/project/globalHome.js +18 -0
  188. package/dist/project/workspaceCatalog.d.ts +10 -0
  189. package/dist/project/workspaceCatalog.js +91 -0
  190. package/dist/projection/projectRun.d.ts +0 -1
  191. package/dist/projection/projectRun.js +0 -1
  192. package/dist/runstore/backup.js +14 -4
  193. package/dist/runstore/port.d.ts +11 -1
  194. package/dist/runstore/restore.js +5 -2
  195. package/dist/runstore/sqlite/SqliteRunStore.d.ts +8 -0
  196. package/dist/runstore/sqlite/SqliteRunStore.js +29 -9
  197. package/dist/runstore/sqlite/migrations/012-trigger-fires.d.ts +7 -0
  198. package/dist/runstore/sqlite/migrations/012-trigger-fires.js +18 -0
  199. package/dist/runstore/sqlite/migrations/index.js +2 -0
  200. package/dist/runstore/stageSnapshot.d.ts +3 -1
  201. package/dist/runstore/stageSnapshot.js +19 -0
  202. package/dist/runstore/workspaceLayout.js +27 -0
  203. package/dist/runstore/writeContainedArtifact.d.ts +1 -0
  204. package/dist/runstore/writeContainedArtifact.js +52 -0
  205. package/dist/runtime/containerLimits.d.ts +0 -3
  206. package/dist/runtime/containerLimits.js +0 -5
  207. package/dist/runtime/credentialBinding.d.ts +3 -0
  208. package/dist/runtime/credentialBinding.js +23 -6
  209. package/dist/runtime/emailSource.js +20 -28
  210. package/dist/runtime/githubPollSource.js +20 -28
  211. package/dist/runtime/pipelineRunner.d.ts +4 -4
  212. package/dist/runtime/pipelineScheduler.d.ts +2 -2
  213. package/dist/runtime/pipelineScheduler.js +3 -0
  214. package/dist/runtime/resumeReconstruct.d.ts +2 -2
  215. package/dist/runtime/resumeTimedOut.d.ts +2 -2
  216. package/dist/runtime/runManager.d.ts +18 -2
  217. package/dist/runtime/runManager.js +95 -30
  218. package/dist/runtime/runRetentionSweep.d.ts +0 -2
  219. package/dist/runtime/runRetentionSweep.js +0 -8
  220. package/dist/runtime/runRetryCoordinator.d.ts +2 -2
  221. package/dist/runtime/scheduleSource.js +15 -24
  222. package/dist/runtime/stageAttemptBootstrap.d.ts +2 -2
  223. package/dist/runtime/stageAttemptBootstrap.js +10 -1
  224. package/dist/runtime/stageProcessLauncher.js +2 -2
  225. package/dist/runtime/stageRoots.js +12 -1
  226. package/dist/runtime/stageRunner.d.ts +2 -2
  227. package/dist/runtime/stageRunner.js +8 -2
  228. package/dist/runtime/stageWorker.js +2 -2
  229. package/dist/runtime/triggerPort.d.ts +5 -3
  230. package/dist/runtime/triggerRunner.d.ts +1 -0
  231. package/dist/runtime/triggerRunner.js +27 -20
  232. package/dist/runtime/webhookAccept.d.ts +25 -0
  233. package/dist/runtime/webhookAccept.js +56 -0
  234. package/dist/server/bootstrap.d.ts +7 -2
  235. package/dist/server/bootstrap.js +15 -1
  236. package/dist/server/controlToken.d.ts +1 -1
  237. package/dist/server/controlToken.js +18 -2
  238. package/dist/server/healthSurfaces.d.ts +12 -0
  239. package/dist/server/healthSurfaces.js +27 -6
  240. package/dist/server/http.d.ts +19 -10
  241. package/dist/server/http.js +605 -85
  242. package/dist/server/liveViewPath.d.ts +9 -0
  243. package/dist/server/liveViewPath.js +8 -0
  244. package/dist/server/liveViewRoutes.d.ts +58 -0
  245. package/dist/server/liveViewRoutes.js +565 -0
  246. package/dist/server/mcpHost.d.ts +4 -2
  247. package/dist/server/mcpHost.js +2 -0
  248. package/dist/server/readCatalogFile.d.ts +29 -0
  249. package/dist/server/readCatalogFile.js +215 -0
  250. package/dist/server/triggerRoutes.d.ts +1 -0
  251. package/dist/server/triggerRoutes.js +200 -73
  252. package/dist/tools/readEmail.d.ts +3 -3
  253. package/dist/tools/writeStageArtifact.d.ts +9 -0
  254. package/dist/tools/writeStageArtifact.js +2 -47
  255. package/dist/types/pipeline.d.ts +1 -1
  256. package/dist/types/stage.d.ts +1 -1
  257. package/dist/types/stageflowManifest.d.ts +1 -1
  258. package/dist/ui/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
  259. package/dist/ui/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
  260. package/dist/ui/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
  261. package/dist/ui/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
  262. package/dist/ui/assets/geist-mono-cyrillic-ext-wght-normal-X_5orZeX.woff2 +0 -0
  263. package/dist/ui/assets/geist-mono-cyrillic-wght-normal-DiZS0aHC.woff2 +0 -0
  264. package/dist/ui/assets/geist-mono-latin-ext-wght-normal-Bwz-egvJ.woff2 +0 -0
  265. package/dist/ui/assets/geist-mono-latin-wght-normal-XN7g48iV.woff2 +0 -0
  266. package/dist/ui/assets/geist-mono-symbols2-wght-normal-CO5SzqOn.woff2 +0 -0
  267. package/dist/ui/assets/geist-mono-vietnamese-wght-normal-DadHysG0.woff2 +0 -0
  268. package/dist/ui/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
  269. package/dist/ui/assets/index-BoFPkKFg.js +256 -0
  270. package/dist/ui/assets/{index-Bv4p1aPK.css → index-CIPbbBUi.css} +1 -1
  271. package/dist/ui/index.html +4 -4
  272. package/dist/workshop/autosave.d.ts +2 -2
  273. package/dist/workshop/autosave.js +4 -6
  274. package/dist/workshop/buildStore.d.ts +2 -0
  275. package/dist/workshop/chatAttachments.d.ts +27 -0
  276. package/dist/workshop/chatAttachments.js +98 -0
  277. package/dist/workshop/chatTurn.d.ts +5 -2
  278. package/dist/workshop/chatTurn.js +22 -18
  279. package/dist/workshop/sessionMutations.d.ts +17 -0
  280. package/dist/workshop/sessionMutations.js +107 -0
  281. package/dist/workshop/sessionStore.d.ts +10 -0
  282. package/dist/workshop/sessionStore.js +52 -0
  283. package/dist/workshop/workshopPin.d.ts +4 -3
  284. package/dist/workshop/workshopPin.js +26 -6
  285. package/dist/workshop/workshopTranscriptTurn.d.ts +8 -0
  286. package/dist/workshop/workshopTranscriptTurn.js +46 -0
  287. package/examples/README.md +1 -1
  288. package/examples/archify-on-pr/README.md +1 -1
  289. package/examples/archify-on-pr/archify-on-pr.pipeline.yaml +0 -1
  290. package/examples/archify-on-pr/author-diagrams.yaml +1 -0
  291. package/examples/conditional-fork/branch-a.yaml +1 -1
  292. package/examples/conditional-fork/decide.yaml +2 -1
  293. package/examples/feature-loop/{implement.yaml → feature-implement.yaml} +1 -1
  294. package/examples/feature-loop/feature-loop.pipeline.yaml +10 -10
  295. package/examples/feature-loop/{plan.yaml → feature-plan.yaml} +1 -1
  296. package/examples/feature-loop/{review.yaml → feature-review.yaml} +1 -1
  297. package/examples/feedback-loop/{implement.yaml → feedback-implement.yaml} +1 -1
  298. package/examples/feedback-loop/feedback-loop-wait-human.pipeline.yaml +9 -9
  299. package/examples/feedback-loop/feedback-loop.pipeline.yaml +9 -9
  300. package/examples/feedback-loop/{plan.yaml → feedback-plan.yaml} +1 -1
  301. package/examples/feedback-loop/{review.yaml → feedback-review.yaml} +1 -1
  302. package/examples/generic-fan-in/{research.yaml → fan-in-research.yaml} +1 -1
  303. package/examples/generic-fan-in/generic-fan-in-accepted.pipeline.yaml +3 -3
  304. package/examples/generic-fan-in/generic-fan-in.pipeline.yaml +3 -3
  305. package/examples/hello-world/{research.yaml → hello-research.yaml} +1 -1
  306. package/examples/hello-world/hello.pipeline.yaml +2 -2
  307. package/examples/mcp-hitl-tour/{review.yaml → mcp-hitl-review.yaml} +1 -1
  308. package/examples/mcp-hitl-tour/mcp-hitl-tour.pipeline.yaml +3 -3
  309. package/examples/oss-issue-contribution/oss-explain-fix.yaml +1 -0
  310. package/examples/oss-issue-contribution/oss-explain-issue.yaml +1 -0
  311. package/examples/oss-issue-contribution/oss-issue-contribution.pipeline.yaml +0 -2
  312. package/examples/stageflow.yaml +6 -0
  313. package/examples/triggers/sample-github-pr.trigger.yaml +12 -0
  314. package/examples/triggers/sample-inbox-email.trigger.yaml +14 -0
  315. package/examples/triggers/sample-manual-hello.trigger.yaml +5 -0
  316. package/examples/triggers/sample-nightly-hello.trigger.yaml +8 -0
  317. package/examples/triggers/sample-signed-webhook.trigger.yaml +11 -0
  318. package/examples/triggers-readiness/README.md +48 -0
  319. package/examples/triggers-readiness/readiness-emit.yaml +18 -0
  320. package/examples/triggers-readiness/readiness.pipeline.yaml +4 -0
  321. package/examples/triggers-readiness/readiness.task.yaml +6 -0
  322. package/examples/triggers-readiness/stageflow.yaml +13 -0
  323. package/examples/triggers-readiness/triggers/readiness-dynamic-manual.trigger.yaml +4 -0
  324. package/examples/triggers-readiness/triggers/readiness-email.trigger.yaml +12 -0
  325. package/examples/triggers-readiness/triggers/readiness-github-pr.trigger.yaml +12 -0
  326. package/examples/triggers-readiness/triggers/readiness-manual.trigger.yaml +5 -0
  327. package/examples/triggers-readiness/triggers/readiness-schedule.trigger.yaml +8 -0
  328. package/examples/triggers-readiness/triggers/readiness-webhook.trigger.yaml +11 -0
  329. package/package.json +9 -1
  330. package/skills/stageflow/references/control-surface.md +1 -1
  331. package/skills/stageflow-author/references/catalog-write-conventions.md +2 -2
  332. package/skills/stageflow-run/SKILL.md +1 -1
  333. package/skills/stageflow-run/references/mcp-call.md +1 -1
  334. package/skills/stageflow-setup/SKILL.md +1 -1
  335. package/dist/ui/assets/index-59cjF0OA.js +0 -133
@@ -1,8 +1,8 @@
1
- import path from "node:path";
2
1
  import { catalogContextFromStageflow } from "../config/resolveCatalogContext.js";
3
2
  import { getCatalogScanPaths } from "../config/browseCatalog.js";
4
3
  import { resolveStageflowContext } from "../project/resolveStageflowContext.js";
5
- import { findCatalogPathById, findTriggerDefinition } from "./triggerCatalog.js";
4
+ import { findCatalogPathById } from "./triggerCatalog.js";
5
+ import { findCatalogTrigger, triggerStoreId, } from "../config/triggerCatalog.js";
6
6
  /**
7
7
  * Resolves a trigger id to its `*.trigger.yaml` catalog definition, resolves its
8
8
  * `pipeline`/`task` refs to catalog files, and starts a real run through
@@ -14,17 +14,22 @@ import { findCatalogPathById, findTriggerDefinition } from "./triggerCatalog.js"
14
14
  * dynamic-mode trigger (`task` absent) requires one.
15
15
  */
16
16
  export async function fireTrigger(triggerId, store, runManager, options = {}) {
17
- const cwd = options.cwd ?? process.cwd();
18
- const ctx = catalogContextFromStageflow(await resolveStageflowContext(cwd));
19
- const scanPaths = await getCatalogScanPaths(ctx);
20
- if (!scanPaths) {
21
- return { ok: false, reason: "No Stageflow catalog found", status: 404 };
22
- }
23
- const found = await findTriggerDefinition(scanPaths.triggerPaths, triggerId);
24
- if (!found) {
25
- return { ok: false, reason: `Trigger not found: ${triggerId}`, status: 404 };
17
+ const bootCwd = options.cwd ?? process.cwd();
18
+ const located = await findCatalogTrigger({
19
+ store,
20
+ bootCwd,
21
+ triggerId,
22
+ projectRootFilter: options.project_root,
23
+ });
24
+ if (!located.ok) {
25
+ return {
26
+ ok: false,
27
+ reason: located.reason,
28
+ status: located.status,
29
+ };
26
30
  }
27
- const { path: triggerPath, definition: trigger } = found;
31
+ const { match } = located;
32
+ const trigger = match.definition;
28
33
  if (!trigger.enabled) {
29
34
  return { ok: false, reason: `Trigger is disabled: ${triggerId}`, status: 409 };
30
35
  }
@@ -45,6 +50,11 @@ export async function fireTrigger(triggerId, store, runManager, options = {}) {
45
50
  code: "trigger.task_required",
46
51
  };
47
52
  }
53
+ const ctx = catalogContextFromStageflow(await resolveStageflowContext(match.rootPath));
54
+ const scanPaths = await getCatalogScanPaths(ctx);
55
+ if (!scanPaths) {
56
+ return { ok: false, reason: "No Stageflow catalog found", status: 404 };
57
+ }
48
58
  const pipelinePath = await findCatalogPathById(scanPaths.pipelinePaths, trigger.pipeline);
49
59
  if (!pipelinePath) {
50
60
  return {
@@ -68,22 +78,19 @@ export async function fireTrigger(triggerId, store, runManager, options = {}) {
68
78
  else {
69
79
  taskInput = suppliedTask;
70
80
  }
71
- const projectRoot = ctx.projectRoot ?? undefined;
72
- const definitionRef = projectRoot !== undefined
73
- ? path.relative(projectRoot, triggerPath).replace(/\\/g, "/")
74
- : triggerPath;
81
+ const storeId = triggerStoreId(match.project_root, trigger.id);
75
82
  await store.upsertTrigger({
76
- id: triggerId,
77
- definitionRef,
83
+ id: storeId,
84
+ definitionRef: match.definition_ref,
78
85
  enabled: trigger.enabled,
79
86
  });
80
87
  const started = await runManager.startRun({
81
88
  pipeline: pipelinePath,
82
89
  task: taskInput,
83
- ...(projectRoot !== undefined ? { projectRoot } : {}),
90
+ projectRoot: match.rootPath,
84
91
  });
85
92
  if (started.ok) {
86
- await store.recordTriggerFired(triggerId, started.runId);
93
+ await store.recordTriggerFired(storeId, started.runId);
87
94
  }
88
95
  return started;
89
96
  }
@@ -0,0 +1,25 @@
1
+ import type { TaskFile } from "../types/task.js";
2
+ import type { TriggerFile } from "../types/trigger.js";
3
+ export type WebhookHeaderMap = {
4
+ readonly [name: string]: string | string[] | undefined;
5
+ };
6
+ export type WebhookAcceptResult = {
7
+ kind: "not_configured";
8
+ } | {
9
+ kind: "bad_signature";
10
+ } | {
11
+ kind: "bad_json";
12
+ error: "Invalid JSON body" | "Invalid JSON body: expected an object";
13
+ } | {
14
+ kind: "no_match";
15
+ } | {
16
+ kind: "fire";
17
+ task?: TaskFile;
18
+ };
19
+ export declare function acceptWebhook(input: {
20
+ trigger: TriggerFile;
21
+ rawBody: Buffer;
22
+ headers: WebhookHeaderMap;
23
+ env: NodeJS.ProcessEnv;
24
+ now?: () => number;
25
+ }): WebhookAcceptResult;
@@ -0,0 +1,56 @@
1
+ import { readSecretFromEnvOrFile } from "../config/secretFromEnvOrFile.js";
2
+ import { matchesEventFilter } from "./triggerEventMatch.js";
3
+ import { verifyHmacSignature } from "./webhookSignature.js";
4
+ export function acceptWebhook(input) {
5
+ const { trigger, rawBody, headers, env } = input;
6
+ const now = input.now ?? Date.now;
7
+ const config = trigger.event?.config;
8
+ const secretRef = typeof config?.secretRef === "string" ? config.secretRef : undefined;
9
+ const header = typeof config?.header === "string" ? config.header : undefined;
10
+ if (secretRef === undefined || header === undefined) {
11
+ return { kind: "not_configured" };
12
+ }
13
+ const scheme = config?.scheme === "base64" ? "base64" : "hex";
14
+ let secret;
15
+ try {
16
+ secret = readSecretFromEnvOrFile(env, secretRef);
17
+ }
18
+ catch {
19
+ secret = undefined;
20
+ }
21
+ if (secret === undefined) {
22
+ return { kind: "not_configured" };
23
+ }
24
+ const headerValue = headers[header.toLowerCase()];
25
+ const signature = Array.isArray(headerValue) ? headerValue[0] : headerValue;
26
+ if (typeof signature !== "string" ||
27
+ signature.length === 0 ||
28
+ !verifyHmacSignature(rawBody, signature, secret, scheme)) {
29
+ return { kind: "bad_signature" };
30
+ }
31
+ let payload;
32
+ try {
33
+ payload = rawBody.length === 0 ? {} : JSON.parse(rawBody.toString("utf8"));
34
+ }
35
+ catch {
36
+ return { kind: "bad_json", error: "Invalid JSON body" };
37
+ }
38
+ if (payload === null || typeof payload !== "object" || Array.isArray(payload)) {
39
+ return { kind: "bad_json", error: "Invalid JSON body: expected an object" };
40
+ }
41
+ const payloadRecord = payload;
42
+ if (!matchesEventFilter(trigger.event?.match, payloadRecord)) {
43
+ return { kind: "no_match" };
44
+ }
45
+ if (trigger.task !== undefined) {
46
+ return { kind: "fire" };
47
+ }
48
+ return {
49
+ kind: "fire",
50
+ task: {
51
+ id: `${trigger.id}-webhook-${now()}`,
52
+ goal: `Handle webhook event for trigger "${trigger.id}"`,
53
+ input: payloadRecord,
54
+ },
55
+ };
56
+ }
@@ -1,9 +1,11 @@
1
1
  import { type A2aHost } from "../a2a/server.js";
2
- import type { AgentPort } from "../agent/port.js";
2
+ import type { StagePort } from "../agent/port.js";
3
3
  import type { ProviderAuthContext } from "../agent/providerAuth.js";
4
4
  import { type RunStoreKind } from "../runstore/createStore.js";
5
+ import { type WorkspaceProvisionResult } from "../project/workspaceCatalog.js";
5
6
  import type { RunStore } from "../runstore/port.js";
6
7
  import type { StoreFilesystemClassification } from "../runstore/storeFilesystem.js";
8
+ import type { StageBrowserSupport } from "../browser/browserHost.js";
7
9
  import { RunManager } from "../runtime/runManager.js";
8
10
  import { emailHostFor } from "../email/host.js";
9
11
  import { EmailTriggers } from "../email/triggers.js";
@@ -13,7 +15,7 @@ import { type HostConfig } from "../config/hostConfig.js";
13
15
  import { bootProviderConfig } from "../agent/bootProviderConfig.js";
14
16
  export declare const DEFAULT_GC_INTERVAL_MS: number;
15
17
  export type StageflowHostOptions = {
16
- agent: AgentPort;
18
+ agent: StagePort;
17
19
  cwd?: string;
18
20
  agentDir?: string;
19
21
  rootDir?: string;
@@ -27,6 +29,8 @@ export type StageflowHostOptions = {
27
29
  hostConfig?: HostConfig;
28
30
  /** Skip HostConfig load (tests that inject store/manager pieces only). */
29
31
  skipHostConfig?: boolean;
32
+ /** Browser support for the runs this Host executes; defaults to the local host with the live view relay. */
33
+ browser?: StageBrowserSupport;
30
34
  emailTriggerQueue?: ConstructorParameters<typeof EmailTriggers>[0]["queue"];
31
35
  };
32
36
  export type StageflowHostBootstrap = {
@@ -48,6 +52,7 @@ export type StageflowHostBootstrap = {
48
52
  /** Periodic retention GC handle when enabled; already `.unref()`'d. */
49
53
  gcInterval?: NodeJS.Timeout;
50
54
  stopGcInterval: () => void;
55
+ workspaceCatalog?: WorkspaceProvisionResult;
51
56
  /** Stops the schedule-trigger tick loop started at boot. */
52
57
  stopScheduleSource: () => void;
53
58
  /** Stops the GitHub poll-trigger loop started at boot. */
@@ -4,12 +4,15 @@ import { createA2aHost } from "../a2a/server.js";
4
4
  import { A2aStore } from "../a2a/store.js";
5
5
  import { createRunStoreWithConnection } from "../runstore/createStore.js";
6
6
  import { resolveA2aConfigPath } from "../a2a/configDiscovery.js";
7
- import { ensureGlobalHome } from "../project/globalHome.js";
7
+ import { ensureProjectRootsFromEnv } from "../project/ensureProjectRootsFromEnv.js";
8
+ import { ensureGlobalHome, globalStageflowHome } from "../project/globalHome.js";
9
+ import { ensureWorkspaceCatalog, } from "../project/workspaceCatalog.js";
8
10
  import { resolveStageflowContext } from "../project/resolveStageflowContext.js";
9
11
  import { findProjectRoot } from "../project/findProjectRoot.js";
10
12
  import { warnDurableRootDiskIfNeeded } from "../runstore/diskUsage.js";
11
13
  import { assertStoreFilesystemSupported } from "../runstore/storeFilesystem.js";
12
14
  import { assertStoreQuickCheck, isSqliteCorruptError, maybeCheckpointResidualWal, rethrowAsStoreIntegrityFailed, } from "../runstore/sqlite/applyStorePragmas.js";
15
+ import { consoleStageBrowserSupport } from "../browser/stageBrowserEnv.js";
13
16
  import { RunManager } from "../runtime/runManager.js";
14
17
  import { PI_CODING_AGENT_DIR_ENV } from "../runtime/stageRoots.js";
15
18
  import { ScheduleSource, triggerTickIntervalMsFromEnv, } from "../runtime/scheduleSource.js";
@@ -82,6 +85,7 @@ export async function bootstrapStageflowHost(options) {
82
85
  const invocationCwd = options.cwd ?? process.cwd();
83
86
  const ctx = await resolveStageflowContext(invocationCwd);
84
87
  const cwd = ctx.invocationCwd;
88
+ void globalStageflowHome();
85
89
  ensureGlobalHome();
86
90
  const cursorKey = readCursorApiKey(env);
87
91
  if (cursorKey !== undefined &&
@@ -227,6 +231,11 @@ export async function bootstrapStageflowHost(options) {
227
231
  }
228
232
  const runChangeBus = options.runChangeBus ?? boundBus ?? createRunChangeBus();
229
233
  const store = wrapRunStoreWithChangeBus(rawStore, runChangeBus);
234
+ await ensureProjectRootsFromEnv(env, store);
235
+ const workspaceCatalog = ensureWorkspaceCatalog(ctx.globalHome);
236
+ if (!workspaceCatalog.ok) {
237
+ bootLog.warn("workspace.provision_failed", workspaceCatalog.reason ?? "unknown");
238
+ }
230
239
  const manager = new RunManager({
231
240
  agent: options.agent,
232
241
  cwd,
@@ -245,6 +254,7 @@ export async function bootstrapStageflowHost(options) {
245
254
  ])),
246
255
  operatorCatalog: { cwd, agentDir },
247
256
  a2aStore,
257
+ browser: options.browser ?? consoleStageBrowserSupport(),
248
258
  });
249
259
  await manager.attachWaitingStages();
250
260
  await manager.reconcileOrphanedStages();
@@ -269,6 +279,9 @@ export async function bootstrapStageflowHost(options) {
269
279
  const result = await fireTrigger(event.triggerId, store, manager, {
270
280
  cwd,
271
281
  task: event.task,
282
+ ...(event.project_root !== undefined
283
+ ? { project_root: event.project_root }
284
+ : {}),
272
285
  });
273
286
  if (!result.ok) {
274
287
  bootLog.error("trigger.fire_failed", `trigger "${event.triggerId}" fire failed: ${result.reason}`);
@@ -362,5 +375,6 @@ export async function bootstrapStageflowHost(options) {
362
375
  stopEmailSource,
363
376
  email: { ...emailHost, triggers: emailTriggers, stop: stopAccountEmail },
364
377
  storeFilesystem,
378
+ workspaceCatalog,
365
379
  };
366
380
  }
@@ -27,7 +27,7 @@ export declare function hasDriveToken(tokens: ControlTokens): boolean;
27
27
  export declare function hasAnyToken(tokens: ControlTokens): boolean;
28
28
  export declare function isLoopbackBind(bind: string): boolean;
29
29
  export declare function refuseBindMessage(bind: string): string;
30
- export declare function assertBindAllowed(bind: string, tokens: ControlTokens): void;
30
+ export declare function assertBindAllowed(bind: string, tokens: ControlTokens, env?: NodeJS.ProcessEnv): void;
31
31
  export declare class BindRefusedError extends Error {
32
32
  readonly exitCode = 1;
33
33
  constructor(message: string);
@@ -1,6 +1,7 @@
1
1
  import { createHash, timingSafeEqual } from "node:crypto";
2
2
  import { readSecretFromEnvOrFile } from "../config/secretFromEnvOrFile.js";
3
3
  import { isLoopbackHostname } from "./allowedHosts.js";
4
+ import { matchLiveViewRoute } from "./liveViewPath.js";
4
5
  const CONTROL_TOKEN_PREFIX = "STAGEFLOW_CONTROL_TOKEN_";
5
6
  const DEFAULT_CALLER_ID = "default";
6
7
  function digest(value) {
@@ -144,9 +145,14 @@ Set one of:
144
145
  STAGEFLOW_CONTROL_TOKEN_<NAME>=<at least 32 characters>
145
146
 
146
147
  Or bind to loopback instead:
147
- --host 127.0.0.1 (or unset STAGEFLOW_BIND)`;
148
+ --host 127.0.0.1 (or unset STAGEFLOW_BIND)
149
+
150
+ Or, only when the published port stays on this machine:
151
+ STAGEFLOW_ALLOW_UNAUTHENTICATED_BIND=1`;
148
152
  }
149
- export function assertBindAllowed(bind, tokens) {
153
+ export function assertBindAllowed(bind, tokens, env = process.env) {
154
+ if (env.STAGEFLOW_ALLOW_UNAUTHENTICATED_BIND === "1")
155
+ return;
150
156
  if (!isLoopbackBind(bind) && !hasDriveToken(tokens)) {
151
157
  throw new BindRefusedError(refuseBindMessage(bind));
152
158
  }
@@ -169,6 +175,14 @@ export class BindRefusedError extends Error {
169
175
  function isTriggerWebhookRoute(method, pathname) {
170
176
  return method === "POST" && /^\/api\/triggers\/[^/]+\/webhook$/.test(pathname);
171
177
  }
178
+ /**
179
+ * Live view routes authenticate themselves: the ticket route checks the bearer
180
+ * scope for the requested mode, and the browser's event stream and input posts
181
+ * carry a ticket-derived cookie instead of a bearer token.
182
+ */
183
+ function isLiveViewRoute(pathname) {
184
+ return matchLiveViewRoute(pathname) !== null;
185
+ }
172
186
  export function requiredScopeFor(method, pathname) {
173
187
  if (pathname === "/mcp")
174
188
  return "drive";
@@ -176,6 +190,8 @@ export function requiredScopeFor(method, pathname) {
176
190
  return null;
177
191
  if (isTriggerWebhookRoute(method, pathname))
178
192
  return null;
193
+ if (isLiveViewRoute(pathname))
194
+ return null;
179
195
  if (pathname === "/api/backup" || pathname.startsWith("/api/backup/")) {
180
196
  return "drive";
181
197
  }
@@ -1,5 +1,17 @@
1
1
  import type { IncomingMessage, ServerResponse } from "node:http";
2
+ import { type CatalogRoot, type ResolveCatalogRootsOptions } from "../config/resolveCatalogRoots.js";
2
3
  import type { StageflowHostBootstrap } from "./bootstrap.js";
4
+ export type CatalogRootApiRecord = {
5
+ project_root: string;
6
+ kind: CatalogRoot["kind"];
7
+ label: string;
8
+ read_only: boolean;
9
+ available: boolean;
10
+ unavailable_reason?: string;
11
+ };
12
+ export declare function catalogRootLabel(root: CatalogRoot): string;
13
+ export declare function mapCatalogRootForApi(root: CatalogRoot): CatalogRootApiRecord;
14
+ export declare function listCatalogRootsForApi(options: ResolveCatalogRootsOptions): Promise<CatalogRootApiRecord[]>;
3
15
  export declare function handleLivez(_req: IncomingMessage, res: ServerResponse): void;
4
16
  export declare function handleReadyz(_req: IncomingMessage, res: ServerResponse, boot: StageflowHostBootstrap): Promise<void>;
5
17
  export declare function buildRichHealthPayload(boot: StageflowHostBootstrap): Promise<Record<string, unknown>>;
@@ -1,12 +1,37 @@
1
+ import path from "node:path";
1
2
  import { getAuthStatus, } from "../agent/providerAuth.js";
2
3
  import { PACKAGE_VERSION, BUILD_SHA } from "../package-meta.js";
3
4
  import { globalStageflowHome } from "../project/globalHome.js";
4
5
  import { redactHostConfig } from "../config/hostConfig.js";
5
- import { resolveCatalogRoots } from "../config/resolveCatalogRoots.js";
6
+ import { resolveCatalogRoots, } from "../config/resolveCatalogRoots.js";
6
7
  import { json } from "./createHttpHost.js";
7
8
  import { livezBody, probeGitVersion, readSchemaHealth, runReadyzChecks, } from "../diagnostics/checks.js";
8
9
  import { buildEgressHealth } from "../net/proxy.js";
9
10
  import { toolchainHealthMap } from "../preflight/toolchain.js";
11
+ export function catalogRootLabel(root) {
12
+ if (root.kind === "workspace")
13
+ return "Workspace";
14
+ if (root.kind === "seeded")
15
+ return "Examples (read-only)";
16
+ const base = path.basename(root.path.replace(/\\/g, "/"));
17
+ return base || root.project_root;
18
+ }
19
+ export function mapCatalogRootForApi(root) {
20
+ return {
21
+ project_root: root.project_root,
22
+ kind: root.kind,
23
+ label: catalogRootLabel(root),
24
+ read_only: root.read_only,
25
+ available: root.available !== false,
26
+ ...(root.available === false && root.unavailable_reason
27
+ ? { unavailable_reason: root.unavailable_reason }
28
+ : {}),
29
+ };
30
+ }
31
+ export async function listCatalogRootsForApi(options) {
32
+ const roots = await resolveCatalogRoots(options);
33
+ return roots.map(mapCatalogRootForApi);
34
+ }
10
35
  function bootProvidersSnapshot(providerBoot) {
11
36
  return providerBoot
12
37
  ? {
@@ -101,11 +126,7 @@ export async function buildRichHealthPayload(boot) {
101
126
  toolchain: toolchainHealthMap(),
102
127
  store_filesystem: boot.storeFilesystem ?? null,
103
128
  egress: buildEgressHealth(),
104
- catalog_roots: catalogRoots.map((r) => ({
105
- project_root: r.project_root,
106
- kind: r.kind,
107
- read_only: r.read_only,
108
- })),
129
+ catalog_roots: catalogRoots.map(mapCatalogRootForApi),
109
130
  boot_providers,
110
131
  providers_live,
111
132
  providers: boot_providers,
@@ -1,18 +1,20 @@
1
- import type { AgentPort } from "../agent/port.js";
1
+ import type { StagePort } from "../agent/port.js";
2
2
  import { type ProviderAuthContext } from "../agent/providerAuth.js";
3
+ import { type LiveViewRoutesOptions } from "./liveViewRoutes.js";
3
4
  import { WorkshopChatSessionRegistry } from "../workshop/chatTurn.js";
4
- import { type OperatorAgentHost } from "../operatorAgent/index.js";
5
+ import { type AgentPort } from "../operatorAgent/index.js";
5
6
  import type { RunStoreKind } from "../runstore/createStore.js";
6
7
  import type { RunStore } from "../runstore/port.js";
7
8
  import type { RunManager } from "../runtime/runManager.js";
8
9
  import type { RunChangeBus } from "../runtime/runChangeBus.js";
10
+ import type { StageBrowserSupport } from "../browser/browserHost.js";
9
11
  import { EmailTriggers } from "../email/triggers.js";
10
12
  import { type AllowedHosts } from "./allowedHosts.js";
11
13
  import { type ControlTokens } from "./controlToken.js";
12
14
  import { DEFAULT_PORT, type HttpHostEnvelope, type HttpHostRouteContext } from "./createHttpHost.js";
13
15
  import { type ShutdownController } from "./shutdown.js";
14
16
  export type UiServerOptions = {
15
- agent: AgentPort;
17
+ agent: StagePort;
16
18
  cwd?: string;
17
19
  agentDir?: string;
18
20
  rootDir?: string;
@@ -28,8 +30,9 @@ export type UiServerOptions = {
28
30
  runChangeBus?: RunChangeBus;
29
31
  allowedHosts?: AllowedHosts;
30
32
  controlTokens?: ControlTokens;
31
- /** Optional Workshop Operator Agent Host (fake in tests). */
32
- workshopOperatorHost?: OperatorAgentHost;
33
+ browser?: StageBrowserSupport;
34
+ /** Optional AgentPort. Workshop is the caller today; tests inject a fake. */
35
+ workshopOperatorHost?: AgentPort;
33
36
  };
34
37
  export declare function defaultUiDistDir(): string;
35
38
  export type OperatorRouteDeps = {
@@ -43,14 +46,16 @@ export type OperatorRouteDeps = {
43
46
  uiDistDir?: string;
44
47
  allowedHosts?: AllowedHosts;
45
48
  controlTokens?: ControlTokens;
49
+ /** Test seams for live view (fake relay, clock, audit sink); production builds everything from persisted state. */
50
+ liveView?: Omit<LiveViewRoutesOptions, "store" | "controlTokens">;
46
51
  /** Live shutdown controller; set after listen so restore can beginDrain. */
47
52
  getShutdown?: () => import("./shutdown.js").ShutdownController | undefined;
48
53
  /**
49
- * Optional Operator Agent Host for Workshop chat (tests inject the fake host).
50
- * Distinct from stage-execution AgentPort. Defaults to live Pi Workshop Author
51
- * (fake remains available via createWorkshopOperatorHost / test injection).
54
+ * Optional AgentPort (tests inject the fake host).
55
+ * Distinct from StagePort. Defaults to resolveAgentPort (Pi).
56
+ * The fake host remains available via createWorkshopOperatorHost.
52
57
  */
53
- workshopOperatorHost?: OperatorAgentHost;
58
+ workshopOperatorHost?: AgentPort;
54
59
  /**
55
60
  * Optional durable Workshop chat registry (host sessions keyed by session id).
56
61
  * Defaults to a registry owned by this route surface.
@@ -64,7 +69,11 @@ export type OperatorRouteDeps = {
64
69
  * `startMcpServer` (headless global-service daemon) — both need the REST
65
70
  * API; only the former needs the UI files.
66
71
  */
67
- export declare function createOperatorRoutes(deps: OperatorRouteDeps): (ctx: HttpHostRouteContext) => Promise<boolean | void>;
72
+ export type OperatorRoutes = ((ctx: HttpHostRouteContext) => Promise<boolean | void>) & {
73
+ /** Ends live view streams, credentials and relay sessions. Browsers are not torn down. */
74
+ dispose(): Promise<void>;
75
+ };
76
+ export declare function createOperatorRoutes(deps: OperatorRouteDeps): OperatorRoutes;
68
77
  export declare function startUiServer(options: UiServerOptions): Promise<HttpHostEnvelope & {
69
78
  shutdown: ShutdownController;
70
79
  }>;