stageflow 0.35.0 → 0.39.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 (320) hide show
  1. package/README.md +18 -8
  2. package/dist/agent/claudeAdapter.js +12 -0
  3. package/dist/agent/piAdapter.d.ts +9 -1
  4. package/dist/agent/piAdapter.js +30 -2
  5. package/dist/agent/piIsolatedMcp.js +14 -2
  6. package/dist/agent/piIsolatedMcpProbe.d.ts +5 -1
  7. package/dist/agent/piIsolatedMcpProbe.js +16 -30
  8. package/dist/agent/port.d.ts +7 -0
  9. package/dist/agents/agentId.d.ts +8 -0
  10. package/dist/agents/agentId.js +27 -0
  11. package/dist/agents/approvalBroker.d.ts +16 -0
  12. package/dist/agents/approvalBroker.js +45 -0
  13. package/dist/agents/authorChat.d.ts +19 -0
  14. package/dist/agents/authorChat.js +63 -0
  15. package/dist/agents/chatTurn.d.ts +23 -0
  16. package/dist/agents/chatTurn.js +77 -0
  17. package/dist/agents/communications/agentmail.d.ts +19 -0
  18. package/dist/agents/communications/agentmail.js +46 -0
  19. package/dist/agents/communications/agentmailListener.d.ts +59 -0
  20. package/dist/agents/communications/agentmailListener.js +183 -0
  21. package/dist/agents/communications/allowlist.d.ts +10 -0
  22. package/dist/agents/communications/allowlist.js +36 -0
  23. package/dist/agents/communications/channelConnections.d.ts +3 -0
  24. package/dist/agents/communications/channelConnections.js +51 -0
  25. package/dist/agents/communications/delivery.d.ts +53 -0
  26. package/dist/agents/communications/delivery.js +142 -0
  27. package/dist/agents/communications/email.d.ts +26 -0
  28. package/dist/agents/communications/email.js +20 -0
  29. package/dist/agents/communications/identity.d.ts +13 -0
  30. package/dist/agents/communications/identity.js +18 -0
  31. package/dist/agents/communications/imessageListener.d.ts +41 -0
  32. package/dist/agents/communications/imessageListener.js +92 -0
  33. package/dist/agents/communications/inbound.d.ts +63 -0
  34. package/dist/agents/communications/inbound.js +143 -0
  35. package/dist/agents/communications/listener.d.ts +36 -0
  36. package/dist/agents/communications/listener.js +38 -0
  37. package/dist/agents/communications/photon.d.ts +19 -0
  38. package/dist/agents/communications/photon.js +38 -0
  39. package/dist/agents/communications/port.d.ts +27 -0
  40. package/dist/agents/communications/port.js +6 -0
  41. package/dist/agents/communications/slack.d.ts +28 -0
  42. package/dist/agents/communications/slack.js +65 -0
  43. package/dist/agents/communications/supervisor.d.ts +36 -0
  44. package/dist/agents/communications/supervisor.js +96 -0
  45. package/dist/agents/communications/telegram.d.ts +19 -0
  46. package/dist/agents/communications/telegram.js +52 -0
  47. package/dist/agents/definitionSummary.d.ts +13 -0
  48. package/dist/agents/definitionSummary.js +91 -0
  49. package/dist/agents/delegate.d.ts +3 -0
  50. package/dist/agents/delegate.js +8 -0
  51. package/dist/agents/errors.d.ts +10 -0
  52. package/dist/agents/errors.js +32 -0
  53. package/dist/agents/guardrails.d.ts +24 -0
  54. package/dist/agents/guardrails.js +39 -0
  55. package/dist/agents/historyFit.d.ts +10 -0
  56. package/dist/agents/historyFit.js +26 -0
  57. package/dist/agents/hostContext.d.ts +54 -0
  58. package/dist/agents/hostContext.js +156 -0
  59. package/dist/agents/ledgers.d.ts +29 -0
  60. package/dist/agents/ledgers.js +31 -0
  61. package/dist/agents/lineDiff.d.ts +12 -0
  62. package/dist/agents/lineDiff.js +46 -0
  63. package/dist/agents/ndjson.d.ts +9 -0
  64. package/dist/agents/ndjson.js +47 -0
  65. package/dist/agents/otlpExport.d.ts +9 -0
  66. package/dist/agents/otlpExport.js +58 -0
  67. package/dist/agents/otlpSink.d.ts +7 -0
  68. package/dist/agents/otlpSink.js +23 -0
  69. package/dist/agents/policy.d.ts +31 -0
  70. package/dist/agents/policy.js +84 -0
  71. package/dist/agents/projectRoot.d.ts +5 -0
  72. package/dist/agents/projectRoot.js +15 -0
  73. package/dist/agents/runtime/piRuntime.d.ts +52 -0
  74. package/dist/agents/runtime/piRuntime.js +474 -0
  75. package/dist/agents/runtime/types.d.ts +77 -0
  76. package/dist/agents/runtime/types.js +26 -0
  77. package/dist/agents/sandbox.d.ts +17 -0
  78. package/dist/agents/sandbox.js +10 -0
  79. package/dist/agents/scheduleSource.d.ts +32 -0
  80. package/dist/agents/scheduleSource.js +100 -0
  81. package/dist/agents/service.d.ts +298 -0
  82. package/dist/agents/service.js +1105 -0
  83. package/dist/agents/sessions.d.ts +38 -0
  84. package/dist/agents/sessions.js +321 -0
  85. package/dist/agents/store.d.ts +277 -0
  86. package/dist/agents/store.js +643 -0
  87. package/dist/agents/trace.d.ts +27 -0
  88. package/dist/agents/trace.js +29 -0
  89. package/dist/agents/turnLifecycle.d.ts +72 -0
  90. package/dist/agents/turnLifecycle.js +157 -0
  91. package/dist/agents/webChat/publicChat.d.ts +36 -0
  92. package/dist/agents/webChat/publicChat.js +290 -0
  93. package/dist/agents/webChat/rateLimit.d.ts +15 -0
  94. package/dist/agents/webChat/rateLimit.js +33 -0
  95. package/dist/agents/webChat/slug.d.ts +2 -0
  96. package/dist/agents/webChat/slug.js +9 -0
  97. package/dist/channels/config.d.ts +11 -0
  98. package/dist/channels/config.js +95 -0
  99. package/dist/channels/configWriter.d.ts +40 -0
  100. package/dist/channels/configWriter.js +148 -0
  101. package/dist/channels/connectionEdits.d.ts +34 -0
  102. package/dist/channels/connectionEdits.js +53 -0
  103. package/dist/channels/errorInfo.d.ts +18 -0
  104. package/dist/channels/errorInfo.js +71 -0
  105. package/dist/channels/errors.d.ts +12 -0
  106. package/dist/channels/errors.js +13 -0
  107. package/dist/channels/health.d.ts +41 -0
  108. package/dist/channels/health.js +99 -0
  109. package/dist/channels/host.d.ts +55 -0
  110. package/dist/channels/host.js +185 -0
  111. package/dist/channels/http.d.ts +31 -0
  112. package/dist/channels/http.js +79 -0
  113. package/dist/channels/index.d.ts +10 -0
  114. package/dist/channels/index.js +9 -0
  115. package/dist/channels/ledger.d.ts +37 -0
  116. package/dist/channels/ledger.js +95 -0
  117. package/dist/channels/providers/agentmail.d.ts +26 -0
  118. package/dist/channels/providers/agentmail.js +94 -0
  119. package/dist/channels/providers/kit.d.ts +40 -0
  120. package/dist/channels/providers/kit.js +78 -0
  121. package/dist/channels/providers/photonImessage.d.ts +45 -0
  122. package/dist/channels/providers/photonImessage.js +188 -0
  123. package/dist/channels/providers/photonWhatsapp.d.ts +49 -0
  124. package/dist/channels/providers/photonWhatsapp.js +146 -0
  125. package/dist/channels/providers/slack.d.ts +25 -0
  126. package/dist/channels/providers/slack.js +102 -0
  127. package/dist/channels/providers/telegram.d.ts +21 -0
  128. package/dist/channels/providers/telegram.js +101 -0
  129. package/dist/channels/providers.d.ts +5 -0
  130. package/dist/channels/providers.js +22 -0
  131. package/dist/channels/registry.d.ts +54 -0
  132. package/dist/channels/registry.js +186 -0
  133. package/dist/channels/secretStore.d.ts +21 -0
  134. package/dist/channels/secretStore.js +75 -0
  135. package/dist/channels/secrets.d.ts +15 -0
  136. package/dist/channels/secrets.js +50 -0
  137. package/dist/channels/service.d.ts +54 -0
  138. package/dist/channels/service.js +307 -0
  139. package/dist/channels/stageChannels.d.ts +45 -0
  140. package/dist/channels/stageChannels.js +110 -0
  141. package/dist/channels/types.d.ts +169 -0
  142. package/dist/channels/types.js +1 -0
  143. package/dist/cli/agentsCommand.d.ts +14 -0
  144. package/dist/cli/agentsCommand.js +291 -0
  145. package/dist/cli/doctorCommand.js +3 -1
  146. package/dist/cli.js +9 -0
  147. package/dist/config/browseCatalog.js +4 -11
  148. package/dist/config/draftPackage.d.ts +2 -0
  149. package/dist/config/draftPackage.js +8 -0
  150. package/dist/config/hostConfig.js +8 -0
  151. package/dist/config/loadAgent.d.ts +266 -0
  152. package/dist/config/loadAgent.js +374 -0
  153. package/dist/config/loadPipeline.js +31 -4
  154. package/dist/config/loadStage.js +15 -0
  155. package/dist/config/mcpHostCatalog.d.ts +50 -0
  156. package/dist/config/mcpHostCatalog.js +405 -0
  157. package/dist/config/mcpOAuth.d.ts +37 -0
  158. package/dist/config/mcpOAuth.js +263 -0
  159. package/dist/config/mcpRedaction.d.ts +42 -0
  160. package/dist/config/mcpRedaction.js +314 -0
  161. package/dist/config/mcpToolCache.d.ts +20 -0
  162. package/dist/config/mcpToolCache.js +43 -0
  163. package/dist/config/mergePipelineIncludes.d.ts +5 -0
  164. package/dist/config/mergePipelineIncludes.js +52 -0
  165. package/dist/config/pipelineStageKeys.js +1 -0
  166. package/dist/config/resolveStageMcpServers.d.ts +35 -3
  167. package/dist/config/resolveStageMcpServers.js +124 -9
  168. package/dist/config/validateCatalog.d.ts +4 -1
  169. package/dist/config/validateCatalog.js +45 -1
  170. package/dist/errors/codes.d.ts +1 -1
  171. package/dist/errors/codes.js +1 -0
  172. package/dist/mcp/agentTools.d.ts +8 -0
  173. package/dist/mcp/agentTools.js +132 -0
  174. package/dist/mcp/catalogTools.js +7 -9
  175. package/dist/mcp/deps.d.ts +6 -0
  176. package/dist/mcp/pipelineAuthorSupport.d.ts +19 -0
  177. package/dist/mcp/pipelineAuthorSupport.js +10 -0
  178. package/dist/mcp/pipelineAuthorTools.d.ts +8 -0
  179. package/dist/mcp/pipelineAuthorTools.js +109 -0
  180. package/dist/mcp/server.js +5 -0
  181. package/dist/mcp/tools.js +4 -0
  182. package/dist/mcp/triggerTools.js +32 -0
  183. package/dist/memory/access.d.ts +36 -0
  184. package/dist/memory/access.js +116 -0
  185. package/dist/memory/agentIssues.d.ts +3 -0
  186. package/dist/memory/agentIssues.js +23 -0
  187. package/dist/memory/bashDeny.d.ts +6 -0
  188. package/dist/memory/bashDeny.js +35 -0
  189. package/dist/memory/host.d.ts +51 -0
  190. package/dist/memory/host.js +394 -0
  191. package/dist/memory/ids.d.ts +15 -0
  192. package/dist/memory/ids.js +31 -0
  193. package/dist/memory/worker.d.ts +1 -0
  194. package/dist/memory/worker.js +84 -0
  195. package/dist/models/catalog.d.ts +113 -0
  196. package/dist/models/catalog.js +238 -0
  197. package/dist/models/response.d.ts +29 -0
  198. package/dist/models/response.js +25 -0
  199. package/dist/operatorAgent/agentAuthorContext.d.ts +17 -0
  200. package/dist/operatorAgent/agentAuthorContext.js +32 -0
  201. package/dist/operatorAgent/fakeHost.js +2 -0
  202. package/dist/operatorAgent/host.js +6 -3
  203. package/dist/operatorAgent/index.d.ts +4 -0
  204. package/dist/operatorAgent/index.js +4 -0
  205. package/dist/operatorAgent/piModel.js +2 -0
  206. package/dist/operatorAgent/profiles/agentAuthor.d.ts +11 -0
  207. package/dist/operatorAgent/profiles/agentAuthor.js +192 -0
  208. package/dist/operatorAgent/profiles/agentAuthorPlaybook.d.ts +1 -0
  209. package/dist/operatorAgent/profiles/agentAuthorPlaybook.js +29 -0
  210. package/dist/operatorAgent/profiles/workshopAuthor.js +2 -2
  211. package/dist/operatorAgent/profiles/workshopAuthorTools.js +3 -3
  212. package/dist/operatorAgent/proposals.d.ts +1 -0
  213. package/dist/operatorAgent/proposals.js +23 -2
  214. package/dist/package-meta.d.ts +1 -1
  215. package/dist/package-meta.js +1 -1
  216. package/dist/preflight/channelChecks.d.ts +17 -0
  217. package/dist/preflight/channelChecks.js +106 -0
  218. package/dist/preflight/pipelinePreflight.d.ts +9 -2
  219. package/dist/preflight/pipelinePreflight.js +10 -1
  220. package/dist/runstore/createStore.d.ts +2 -0
  221. package/dist/runstore/createStore.js +8 -0
  222. package/dist/runstore/overviewSummary.d.ts +56 -0
  223. package/dist/runstore/overviewSummary.js +134 -0
  224. package/dist/runstore/port.d.ts +3 -0
  225. package/dist/runstore/sqlite/SqliteRunStore.d.ts +2 -0
  226. package/dist/runstore/sqlite/SqliteRunStore.js +18 -0
  227. package/dist/runstore/sqlite/migrations/013-agents.d.ts +12 -0
  228. package/dist/runstore/sqlite/migrations/013-agents.js +156 -0
  229. package/dist/runstore/sqlite/migrations/014-agent-deliveries.d.ts +11 -0
  230. package/dist/runstore/sqlite/migrations/014-agent-deliveries.js +32 -0
  231. package/dist/runstore/sqlite/migrations/index.js +4 -0
  232. package/dist/runtime/pipelineRunner.js +3 -1
  233. package/dist/runtime/repositoryMaterialize.d.ts +1 -1
  234. package/dist/runtime/runManager.js +4 -1
  235. package/dist/runtime/stageAttemptBootstrap.js +31 -1
  236. package/dist/runtime/stageEnvironment.d.ts +2 -0
  237. package/dist/runtime/stageEnvironment.js +6 -1
  238. package/dist/runtime/stageProcessLauncher.js +54 -1
  239. package/dist/runtime/stageSecrets.d.ts +6 -1
  240. package/dist/runtime/stageSecrets.js +34 -1
  241. package/dist/server/agentAuthorRoutes.d.ts +5 -0
  242. package/dist/server/agentAuthorRoutes.js +64 -0
  243. package/dist/server/agentRoutes.d.ts +5 -0
  244. package/dist/server/agentRoutes.js +323 -0
  245. package/dist/server/bootstrap.d.ts +11 -0
  246. package/dist/server/bootstrap.js +40 -10
  247. package/dist/server/channelRoutes.d.ts +9 -0
  248. package/dist/server/channelRoutes.js +88 -0
  249. package/dist/server/controlToken.js +8 -0
  250. package/dist/server/http.d.ts +8 -1
  251. package/dist/server/http.js +183 -20
  252. package/dist/server/mcpHost.js +1 -0
  253. package/dist/server/memoryRoutes.d.ts +5 -0
  254. package/dist/server/memoryRoutes.js +146 -0
  255. package/dist/server/projectMcpRoutes.d.ts +1 -0
  256. package/dist/server/projectMcpRoutes.js +241 -3
  257. package/dist/toolkit/guard.d.ts +27 -0
  258. package/dist/toolkit/guard.js +98 -0
  259. package/dist/toolkit/index.d.ts +48 -0
  260. package/dist/toolkit/index.js +82 -0
  261. package/dist/toolkit/meta.d.ts +36 -0
  262. package/dist/toolkit/meta.js +117 -0
  263. package/dist/toolkit/profiles.d.ts +13 -0
  264. package/dist/toolkit/profiles.js +25 -0
  265. package/dist/toolkit/record.d.ts +15 -0
  266. package/dist/toolkit/record.js +17 -0
  267. package/dist/tools/memoryTools.d.ts +95 -0
  268. package/dist/tools/memoryTools.js +179 -0
  269. package/dist/tools/sendMessage.d.ts +21 -0
  270. package/dist/tools/sendMessage.js +25 -0
  271. package/dist/types/pipeline.d.ts +7 -1
  272. package/dist/types/stage.d.ts +15 -0
  273. package/dist/ui/assets/AssistantRuntimeProvider-CsiPFhCT.js +9 -0
  274. package/dist/ui/assets/MarkdownText-D7tYaIFO.js +29 -0
  275. package/dist/ui/assets/ReadonlyStore-BfXqHykm.js +6 -0
  276. package/dist/ui/assets/Tooltip-DrpoRRNi.js +1 -0
  277. package/dist/ui/assets/chat-BbLukq9W.js +5 -0
  278. package/dist/ui/assets/chat-zIZU_bP1.css +2 -0
  279. package/dist/ui/assets/jsx-runtime-iVoFAvQ_.js +1 -0
  280. package/dist/ui/assets/{index-CIPbbBUi.css → main-BFo79krC.css} +1 -1
  281. package/dist/ui/assets/main-CijYMeM0.js +259 -0
  282. package/dist/ui/chat.html +25 -0
  283. package/dist/ui/index.html +6 -2
  284. package/dist/workshop/modelSettings.d.ts +2 -2
  285. package/dist/workshop/modelSettings.js +5 -11
  286. package/examples/README.md +1 -0
  287. package/examples/channels-smoke/README.md +23 -0
  288. package/examples/channels-smoke/channels-smoke.pipeline.yaml +11 -0
  289. package/examples/channels-smoke/channels-smoke.task.yaml +3 -0
  290. package/examples/channels-smoke/send-email.yaml +32 -0
  291. package/examples/channels-smoke/send-text.yaml +31 -0
  292. package/examples/github-release/README.md +1 -1
  293. package/examples/memory/README.md +99 -0
  294. package/examples/memory/desk-outage.task.yaml +15 -0
  295. package/examples/memory/desk-refund.task.yaml +15 -0
  296. package/examples/memory/desk-revisit-outage.task.yaml +11 -0
  297. package/examples/memory/desk-revisit.pipeline.yaml +123 -0
  298. package/examples/memory/desk.pipeline.yaml +192 -0
  299. package/examples/memory/file-card.pipeline.yaml +39 -0
  300. package/examples/memory/file-ledger.task.yaml +22 -0
  301. package/examples/memory/file-release.task.yaml +24 -0
  302. package/examples/memory/file-rich.pipeline.yaml +40 -0
  303. package/examples/memory/file-ticket.task.yaml +7 -0
  304. package/examples/memory/file-timeline.task.yaml +28 -0
  305. package/examples/memory/find-card.pipeline.yaml +46 -0
  306. package/examples/memory/find-ticket.task.yaml +7 -0
  307. package/examples/memory/missing.pipeline.yaml +16 -0
  308. package/examples/memory/recall.pipeline.yaml +24 -0
  309. package/examples/memory/recall.task.yaml +5 -0
  310. package/examples/memory/remember-ada.task.yaml +6 -0
  311. package/examples/memory/remember-grace.task.yaml +6 -0
  312. package/examples/memory/remember.pipeline.yaml +58 -0
  313. package/examples/memory/stageflow.yaml +12 -0
  314. package/examples/memory/update-card.pipeline.yaml +43 -0
  315. package/examples/memory/update-ledger.task.yaml +23 -0
  316. package/examples/memory/update-rich.pipeline.yaml +44 -0
  317. package/examples/memory/update-ticket.task.yaml +7 -0
  318. package/examples/stage-mcp/README.md +1 -1
  319. package/package.json +9 -3
  320. package/dist/ui/assets/index-BoFPkKFg.js +0 -256
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Pure description of Stageflow's own tools: which group each belongs to and
3
+ * how risky it is. No handlers live here, so config validation and the console
4
+ * can import it without pulling in the runtime.
5
+ */
6
+ export type ToolRisk = "read" | "write" | "destructive" | "external";
7
+ export type ToolGroupId = "discover" | "runs.read" | "runs.control" | "runs.cleanup" | "gates.read" | "gates.decide" | "triggers" | "agents.read" | "agents.manage" | "agents.cleanup" | "agents.converse" | "pipelines.author";
8
+ export type ToolGroup = {
9
+ id: ToolGroupId;
10
+ title: string;
11
+ summary: string;
12
+ /** Never offered to agents: these decide things a person must decide (approvals, gates). */
13
+ operatorOnly?: true;
14
+ };
15
+ export declare const TOOL_GROUPS: readonly ToolGroup[];
16
+ export type ToolMeta = {
17
+ group: ToolGroupId;
18
+ risk: ToolRisk;
19
+ /** Not offered to agents even though its group is. */
20
+ operatorOnly?: true;
21
+ };
22
+ export declare const TOOL_META: Readonly<Record<string, ToolMeta>>;
23
+ export type StageflowGrants = {
24
+ groups: readonly string[];
25
+ tools: readonly string[];
26
+ };
27
+ /** The grant id the policy gate and `approvals.ask_first` use for a Stageflow tool. */
28
+ export declare const STAGEFLOW_GRANT_PREFIX = "stageflow.";
29
+ export declare const stageflowGrantId: (tool: string) => string;
30
+ export declare function isToolGroupId(value: string): value is ToolGroupId;
31
+ export declare function isOperatorOnlyGroup(group: string): boolean;
32
+ export declare function isOperatorOnlyTool(name: string): boolean;
33
+ /** Tools of a group an agent may hold; operator-only tools are left out. */
34
+ export declare function toolsInGroup(group: string): string[];
35
+ /** Every Stageflow tool name a definition grants, whole groups and single tools together. */
36
+ export declare function grantedStageflowTools(grants: StageflowGrants): string[];
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Pure description of Stageflow's own tools: which group each belongs to and
3
+ * how risky it is. No handlers live here, so config validation and the console
4
+ * can import it without pulling in the runtime.
5
+ */
6
+ export const TOOL_GROUPS = [
7
+ { id: "discover", title: "Discover the project", summary: "List pipelines, tasks, skills, models and providers; validate and preflight." },
8
+ { id: "runs.read", title: "Watch runs", summary: "Read runs, stage events, logs, envelopes, artifacts and checkout diffs." },
9
+ { id: "runs.control", title: "Run and recover pipelines", summary: "Start, rerun, retry, resume and recover runs." },
10
+ { id: "runs.cleanup", title: "Cancel and delete runs", summary: "Cancel runs, abandon stages, delete runs and collect old ones. Destructive." },
11
+ { id: "gates.read", title: "See what is waiting", summary: "List the gates and questions waiting on a person." },
12
+ { id: "gates.decide", title: "Decide gates and approvals", summary: "Answer gates and approve or deny agent actions. Only a person can do this.", operatorOnly: true },
13
+ { id: "triggers", title: "Triggers", summary: "List, create and fire triggers." },
14
+ { id: "agents.read", title: "Look at agents", summary: "List agents, revisions and sessions." },
15
+ { id: "agents.manage", title: "Manage agents", summary: "Create, save, enable, disable and restore agents." },
16
+ { id: "agents.cleanup", title: "Archive agents", summary: "Archive an agent. Destructive." },
17
+ { id: "agents.converse", title: "Talk to agents", summary: "Chat with an agent and stop its running turn." },
18
+ { id: "pipelines.author", title: "Author pipelines and tasks", summary: "Read, create and edit pipelines, stages and tasks directly on disk." },
19
+ ];
20
+ const t = (group, risk, operatorOnly) => ({ group, risk, ...(operatorOnly ? { operatorOnly } : {}) });
21
+ export const TOOL_META = {
22
+ get_started: t("discover", "read", true),
23
+ list_skills: t("discover", "read"),
24
+ list_pipelines: t("discover", "read"),
25
+ list_tasks: t("discover", "read"),
26
+ list_models: t("discover", "read"),
27
+ list_providers: t("discover", "read"),
28
+ get_health: t("discover", "read"),
29
+ preflight: t("discover", "read"),
30
+ validate: t("discover", "read"),
31
+ describe_pipeline: t("discover", "read"),
32
+ list_project_mcp: t("discover", "read"),
33
+ probe_project_mcp: t("discover", "external"),
34
+ list_runs: t("runs.read", "read"),
35
+ get_run: t("runs.read", "read"),
36
+ export_run: t("runs.read", "read"),
37
+ read_artifact: t("runs.read", "read"),
38
+ wait_run: t("runs.read", "read"),
39
+ list_stage_events: t("runs.read", "read"),
40
+ tail_stage_log: t("runs.read", "read"),
41
+ get_stage_verification: t("runs.read", "read"),
42
+ get_envelope: t("runs.read", "read"),
43
+ list_checkout_changes: t("runs.read", "read"),
44
+ get_run_diff: t("runs.read", "read"),
45
+ read_checkout_file: t("runs.read", "read"),
46
+ start_run: t("runs.control", "write"),
47
+ run_stage: t("runs.control", "write"),
48
+ rerun: t("runs.control", "write"),
49
+ retry_stage: t("runs.control", "write"),
50
+ resume_stage: t("runs.control", "write"),
51
+ recover_manual_stage: t("runs.control", "write"),
52
+ stop_manual_recovery: t("runs.control", "write"),
53
+ cancel_run: t("runs.cleanup", "destructive"),
54
+ abandon_stage: t("runs.cleanup", "destructive"),
55
+ delete_run: t("runs.cleanup", "destructive"),
56
+ gc_runs: t("runs.cleanup", "destructive"),
57
+ list_waiting: t("gates.read", "read"),
58
+ get_waiting_summary: t("gates.read", "read"),
59
+ answer_gate: t("gates.decide", "write", true),
60
+ decide_feedback_loop: t("gates.decide", "write", true),
61
+ list_triggers: t("triggers", "read"),
62
+ get_trigger: t("triggers", "read"),
63
+ create_trigger: t("triggers", "write"),
64
+ update_trigger: t("triggers", "write"),
65
+ set_trigger_enabled: t("triggers", "write"),
66
+ fire_trigger: t("triggers", "external"),
67
+ list_agents: t("agents.read", "read"),
68
+ get_agent: t("agents.read", "read"),
69
+ validate_agent: t("agents.read", "read"),
70
+ list_agent_revisions: t("agents.read", "read"),
71
+ get_agent_session: t("agents.read", "read"),
72
+ list_agent_sessions: t("agents.read", "read"),
73
+ create_agent: t("agents.manage", "write"),
74
+ save_agent: t("agents.manage", "write"),
75
+ enable_agent: t("agents.manage", "write"),
76
+ disable_agent: t("agents.manage", "write"),
77
+ restore_agent_revision: t("agents.manage", "write"),
78
+ archive_agent: t("agents.cleanup", "destructive"),
79
+ agent_chat: t("agents.converse", "external"),
80
+ stop_agent_session: t("agents.converse", "write"),
81
+ approve_agent_action: t("gates.decide", "write", true),
82
+ deny_agent_action: t("gates.decide", "write", true),
83
+ read_pipeline: t("pipelines.author", "read"),
84
+ create_pipeline: t("pipelines.author", "write"),
85
+ edit_pipeline: t("pipelines.author", "write"),
86
+ create_stage: t("pipelines.author", "write"),
87
+ edit_stage: t("pipelines.author", "write"),
88
+ create_task: t("pipelines.author", "write"),
89
+ edit_task: t("pipelines.author", "write"),
90
+ };
91
+ /** The grant id the policy gate and `approvals.ask_first` use for a Stageflow tool. */
92
+ export const STAGEFLOW_GRANT_PREFIX = "stageflow.";
93
+ export const stageflowGrantId = (tool) => `${STAGEFLOW_GRANT_PREFIX}${tool}`;
94
+ export function isToolGroupId(value) {
95
+ return TOOL_GROUPS.some((group) => group.id === value);
96
+ }
97
+ export function isOperatorOnlyGroup(group) {
98
+ return TOOL_GROUPS.some((entry) => entry.id === group && entry.operatorOnly === true);
99
+ }
100
+ export function isOperatorOnlyTool(name) {
101
+ const meta = TOOL_META[name];
102
+ return meta !== undefined && (meta.operatorOnly === true || isOperatorOnlyGroup(meta.group));
103
+ }
104
+ /** Tools of a group an agent may hold; operator-only tools are left out. */
105
+ export function toolsInGroup(group) {
106
+ return Object.entries(TOOL_META)
107
+ .filter(([name, meta]) => meta.group === group && !isOperatorOnlyTool(name))
108
+ .map(([name]) => name);
109
+ }
110
+ /** Every Stageflow tool name a definition grants, whole groups and single tools together. */
111
+ export function grantedStageflowTools(grants) {
112
+ const names = new Set(grants.tools.filter((tool) => tool in TOOL_META && !isOperatorOnlyTool(tool)));
113
+ for (const group of grants.groups)
114
+ for (const tool of toolsInGroup(group))
115
+ names.add(tool);
116
+ return [...names].sort();
117
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * The Workshop and Agent-author profiles are agents with a fixed grant list.
3
+ * Their tools are checked through the same grant-id check as any agent's tools,
4
+ * so there is one permission layer. The lists are literals so this module has no
5
+ * dependency on the profiles; tests keep them equal to the profiles' tool names.
6
+ */
7
+ export declare const PROFILE_GRANTS: Readonly<Record<string, {
8
+ prefix: string;
9
+ tools: readonly string[];
10
+ }>>;
11
+ export declare function profileGrantIds(profileId: string): Set<string>;
12
+ /** True when the profile holds the grant for this tool. Unknown profiles hold nothing. */
13
+ export declare function profileMayUse(profileId: string, tool: string): boolean;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * The Workshop and Agent-author profiles are agents with a fixed grant list.
3
+ * Their tools are checked through the same grant-id check as any agent's tools,
4
+ * so there is one permission layer. The lists are literals so this module has no
5
+ * dependency on the profiles; tests keep them equal to the profiles' tool names.
6
+ */
7
+ export const PROFILE_GRANTS = {
8
+ "workshop-author": {
9
+ prefix: "workshop.",
10
+ tools: ["list_builds", "focus_build", "create_build", "read_draft", "validate_draft", "create_pipeline", "edit_pipeline", "create_stage", "edit_stage", "create_task", "edit_task", "save", "propose_draft", "retrieve_docs"],
11
+ },
12
+ "agent-author": {
13
+ prefix: "agent_author.",
14
+ tools: ["read_project_file", "list_project_files", "list_mcp_servers", "update_agent_draft"],
15
+ },
16
+ };
17
+ export function profileGrantIds(profileId) {
18
+ const grants = PROFILE_GRANTS[profileId];
19
+ return new Set((grants?.tools ?? []).map((tool) => `${grants.prefix}${tool}`));
20
+ }
21
+ /** True when the profile holds the grant for this tool. Unknown profiles hold nothing. */
22
+ export function profileMayUse(profileId, tool) {
23
+ const grants = PROFILE_GRANTS[profileId];
24
+ return grants !== undefined && profileGrantIds(profileId).has(`${grants.prefix}${tool}`);
25
+ }
@@ -0,0 +1,15 @@
1
+ import type { ZodType } from "zod";
2
+ import type { McpToolDeps } from "../mcp/deps.js";
3
+ /** An MCP tool as registered: its name, text, input schema and handler. */
4
+ export type RecordedTool = {
5
+ name: string;
6
+ description: string;
7
+ inputSchema: ZodType | undefined;
8
+ readOnlyHint: boolean | undefined;
9
+ handler: (args: Record<string, unknown>, ctx: unknown) => unknown;
10
+ };
11
+ /**
12
+ * Run the real MCP registration against a recorder instead of a server, so the
13
+ * toolkit describes exactly the tools the MCP surface exposes, with no second list to drift.
14
+ */
15
+ export declare function recordMcpTools(deps: McpToolDeps): RecordedTool[];
@@ -0,0 +1,17 @@
1
+ import { registerMcpTools } from "../mcp/tools.js";
2
+ /**
3
+ * Run the real MCP registration against a recorder instead of a server, so the
4
+ * toolkit describes exactly the tools the MCP surface exposes, with no second list to drift.
5
+ */
6
+ export function recordMcpTools(deps) {
7
+ const tools = [];
8
+ const recorder = {
9
+ registerTool(name, config, handler) {
10
+ tools.push({ name, description: config.description ?? "", inputSchema: config.inputSchema, readOnlyHint: config.annotations?.readOnlyHint, handler });
11
+ },
12
+ registerResource() { },
13
+ registerPrompt() { },
14
+ };
15
+ registerMcpTools(recorder, deps);
16
+ return tools;
17
+ }
@@ -0,0 +1,95 @@
1
+ import { Type } from "typebox";
2
+ import { type StageMemory } from "../memory/access.js";
3
+ type ToolResult = {
4
+ content: {
5
+ type: "text";
6
+ text: string;
7
+ }[];
8
+ details: unknown;
9
+ isError?: boolean;
10
+ };
11
+ export declare function createReadMemoryTool(memory: StageMemory): {
12
+ name: string;
13
+ label: string;
14
+ description: string;
15
+ parameters: Type.TObject<{
16
+ memory: Type.TString;
17
+ }>;
18
+ execute(_toolCallId: string, input: unknown): Promise<ToolResult>;
19
+ };
20
+ export declare function createReplaceMemoryTool(memory: StageMemory): {
21
+ name: string;
22
+ label: string;
23
+ description: string;
24
+ parameters: Type.TObject<{
25
+ memory: Type.TString;
26
+ content: Type.TString;
27
+ }>;
28
+ execute(_toolCallId: string, input: unknown): Promise<ToolResult>;
29
+ };
30
+ export declare function createAddMemoryCardTool(memory: StageMemory): {
31
+ name: string;
32
+ label: string;
33
+ description: string;
34
+ parameters: Type.TObject<{
35
+ memory: Type.TString;
36
+ key: Type.TString;
37
+ content: Type.TString;
38
+ }>;
39
+ execute(_toolCallId: string, input: unknown): Promise<ToolResult>;
40
+ };
41
+ export declare function createUpdateMemoryCardTool(memory: StageMemory): {
42
+ name: string;
43
+ label: string;
44
+ description: string;
45
+ parameters: Type.TObject<{
46
+ memory: Type.TString;
47
+ key: Type.TString;
48
+ content: Type.TString;
49
+ }>;
50
+ execute(_toolCallId: string, input: unknown): Promise<ToolResult>;
51
+ };
52
+ export declare function createReadMemoryCardTool(memory: StageMemory): {
53
+ name: string;
54
+ label: string;
55
+ description: string;
56
+ parameters: Type.TObject<{
57
+ memory: Type.TString;
58
+ key: Type.TString;
59
+ }>;
60
+ execute(_toolCallId: string, input: unknown): Promise<ToolResult>;
61
+ };
62
+ export declare function createSearchMemoryCardsTool(memory: StageMemory): {
63
+ name: string;
64
+ label: string;
65
+ description: string;
66
+ parameters: Type.TObject<{
67
+ memory: Type.TString;
68
+ query: Type.TString;
69
+ }>;
70
+ execute(_toolCallId: string, input: unknown): Promise<ToolResult>;
71
+ };
72
+ export declare function memoryPrompt(memory: StageMemory): Promise<string>;
73
+ /** Prompt text and tools for one attached-memory session. */
74
+ export declare function memorySession(memory: StageMemory): {
75
+ prompt: string;
76
+ tools: {
77
+ name: string;
78
+ label: string;
79
+ description: string;
80
+ parameters: Type.TObject<{
81
+ memory: Type.TString;
82
+ }>;
83
+ execute(_toolCallId: string, input: unknown): Promise<ToolResult>;
84
+ }[];
85
+ };
86
+ export declare function createAttachedMemoryTools(memory: StageMemory): {
87
+ name: string;
88
+ label: string;
89
+ description: string;
90
+ parameters: Type.TObject<{
91
+ memory: Type.TString;
92
+ }>;
93
+ execute(_toolCallId: string, input: unknown): Promise<ToolResult>;
94
+ }[];
95
+ export {};
@@ -0,0 +1,179 @@
1
+ import { Type } from "typebox";
2
+ import { MEMORY_KEY_MAX, MEMORY_PAGE_CAP } from "../memory/ids.js";
3
+ import { MemoryError } from "../memory/host.js";
4
+ import { formatMemoryPrompt } from "../memory/access.js";
5
+ function fault(error) {
6
+ return { code: error instanceof MemoryError ? error.code : "MEMORY_UNREADABLE" };
7
+ }
8
+ function refused(error) {
9
+ const details = fault(error);
10
+ return { content: [{ type: "text", text: JSON.stringify(details) }], details, isError: true };
11
+ }
12
+ export function createReadMemoryTool(memory) {
13
+ return {
14
+ name: "read_memory",
15
+ label: "Read memory",
16
+ description: "Read the whole page of a memory attached to this stage or agent. Pass the memory id.",
17
+ parameters: Type.Object({
18
+ memory: Type.String(),
19
+ }),
20
+ async execute(_toolCallId, input) {
21
+ try {
22
+ const id = input.memory;
23
+ if (typeof id !== "string")
24
+ throw new MemoryError("MEMORY_INVALID_ID");
25
+ const body = await memory.read(id);
26
+ return { content: [{ type: "text", text: body }], details: { memory: id } };
27
+ }
28
+ catch (error) {
29
+ return refused(error);
30
+ }
31
+ },
32
+ };
33
+ }
34
+ export function createReplaceMemoryTool(memory) {
35
+ return {
36
+ name: "replace_memory",
37
+ label: "Replace memory",
38
+ description: "Replace the whole page of a memory attached to this stage or agent. Pass the memory id and the full new page. A page over the character cap is refused.",
39
+ parameters: Type.Object({
40
+ memory: Type.String(),
41
+ content: Type.String({ maxLength: MEMORY_PAGE_CAP }),
42
+ }),
43
+ async execute(_toolCallId, input) {
44
+ try {
45
+ const args = input;
46
+ if (typeof args.memory !== "string")
47
+ throw new MemoryError("MEMORY_INVALID_ID");
48
+ if (typeof args.content !== "string")
49
+ throw new MemoryError("MEMORY_TOO_LARGE");
50
+ await memory.replace(args.memory, args.content);
51
+ return { content: [{ type: "text", text: "ok" }], details: { memory: args.memory } };
52
+ }
53
+ catch (error) {
54
+ return refused(error);
55
+ }
56
+ },
57
+ };
58
+ }
59
+ function cardWriteArgs(input) {
60
+ const args = input;
61
+ if (typeof args.memory !== "string")
62
+ throw new MemoryError("MEMORY_INVALID_ID");
63
+ if (typeof args.key !== "string")
64
+ throw new MemoryError("MEMORY_INVALID_KEY");
65
+ if (typeof args.content !== "string")
66
+ throw new MemoryError("MEMORY_TOO_LARGE");
67
+ return { memory: args.memory, key: args.key, content: args.content };
68
+ }
69
+ const cardParameters = Type.Object({
70
+ memory: Type.String(),
71
+ key: Type.String({ maxLength: MEMORY_KEY_MAX }),
72
+ content: Type.String({ maxLength: MEMORY_PAGE_CAP }),
73
+ });
74
+ export function createAddMemoryCardTool(memory) {
75
+ return {
76
+ name: "add_memory_card",
77
+ label: "Add memory card",
78
+ description: "Add a card to a memory attached to this stage or agent. Pass the memory id, the card key, and the card body. A second add of the same key is refused.",
79
+ parameters: cardParameters,
80
+ async execute(_toolCallId, input) {
81
+ try {
82
+ const args = cardWriteArgs(input);
83
+ await memory.addCard(args.memory, args.key, args.content);
84
+ return { content: [{ type: "text", text: "ok" }], details: { memory: args.memory, key: args.key } };
85
+ }
86
+ catch (error) {
87
+ return refused(error);
88
+ }
89
+ },
90
+ };
91
+ }
92
+ export function createUpdateMemoryCardTool(memory) {
93
+ return {
94
+ name: "update_memory_card",
95
+ label: "Update memory card",
96
+ description: "Replace the current body of a card on a memory attached to this stage or agent. Pass the memory id, the card key, and the new body.",
97
+ parameters: cardParameters,
98
+ async execute(_toolCallId, input) {
99
+ try {
100
+ const args = cardWriteArgs(input);
101
+ await memory.updateCard(args.memory, args.key, args.content);
102
+ return { content: [{ type: "text", text: "ok" }], details: { memory: args.memory, key: args.key } };
103
+ }
104
+ catch (error) {
105
+ return refused(error);
106
+ }
107
+ },
108
+ };
109
+ }
110
+ export function createReadMemoryCardTool(memory) {
111
+ return {
112
+ name: "read_memory_card",
113
+ label: "Read memory card",
114
+ description: "Read the current body of a card on a memory attached to this stage or agent. Pass the memory id and the card key.",
115
+ parameters: Type.Object({
116
+ memory: Type.String(),
117
+ key: Type.String({ maxLength: MEMORY_KEY_MAX }),
118
+ }),
119
+ async execute(_toolCallId, input) {
120
+ try {
121
+ const args = input;
122
+ if (typeof args.memory !== "string")
123
+ throw new MemoryError("MEMORY_INVALID_ID");
124
+ if (typeof args.key !== "string")
125
+ throw new MemoryError("MEMORY_INVALID_KEY");
126
+ const body = await memory.readCard(args.memory, args.key);
127
+ return { content: [{ type: "text", text: body }], details: { memory: args.memory, key: args.key } };
128
+ }
129
+ catch (error) {
130
+ return refused(error);
131
+ }
132
+ },
133
+ };
134
+ }
135
+ export function createSearchMemoryCardsTool(memory) {
136
+ return {
137
+ name: "search_memory_cards",
138
+ label: "Search memory cards",
139
+ description: "Search the current cards of a memory attached to this stage or agent. Pass the memory id and a query. Returns matching keys and short snippets.",
140
+ parameters: Type.Object({
141
+ memory: Type.String(),
142
+ query: Type.String(),
143
+ }),
144
+ async execute(_toolCallId, input) {
145
+ try {
146
+ const args = input;
147
+ if (typeof args.memory !== "string")
148
+ throw new MemoryError("MEMORY_INVALID_ID");
149
+ if (typeof args.query !== "string")
150
+ throw new MemoryError("MEMORY_UNREADABLE");
151
+ const hits = await memory.searchCards(args.memory, args.query);
152
+ return { content: [{ type: "text", text: JSON.stringify(hits) }], details: { memory: args.memory } };
153
+ }
154
+ catch (error) {
155
+ return refused(error);
156
+ }
157
+ },
158
+ };
159
+ }
160
+ export async function memoryPrompt(memory) {
161
+ return formatMemoryPrompt(await memory.refreshAttachments());
162
+ }
163
+ /** Prompt text and tools for one attached-memory session. */
164
+ export function memorySession(memory) {
165
+ return {
166
+ prompt: formatMemoryPrompt(memory.attachments),
167
+ tools: createAttachedMemoryTools(memory),
168
+ };
169
+ }
170
+ export function createAttachedMemoryTools(memory) {
171
+ return [
172
+ createReadMemoryTool(memory),
173
+ createReplaceMemoryTool(memory),
174
+ createAddMemoryCardTool(memory),
175
+ createUpdateMemoryCardTool(memory),
176
+ createReadMemoryCardTool(memory),
177
+ createSearchMemoryCardsTool(memory),
178
+ ];
179
+ }
@@ -0,0 +1,21 @@
1
+ import { Type } from "typebox";
2
+ import { type StageChannels } from "../channels/host.js";
3
+ export declare function createSendMessageTool(channels: StageChannels): {
4
+ name: string;
5
+ label: string;
6
+ description: string;
7
+ parameters: Type.TObject<{
8
+ channel: Type.TOptional<Type.TString>;
9
+ text: Type.TString;
10
+ subject: Type.TOptional<Type.TString>;
11
+ operationKey: Type.TString;
12
+ }>;
13
+ execute(_toolCallId: string, input: unknown): Promise<{
14
+ content: {
15
+ type: "text";
16
+ text: string;
17
+ }[];
18
+ details: unknown;
19
+ isError?: boolean;
20
+ }>;
21
+ };
@@ -0,0 +1,25 @@
1
+ import { Type } from "typebox";
2
+ import { MAX_MESSAGE_TEXT, channelFault } from "../channels/host.js";
3
+ export function createSendMessageTool(channels) {
4
+ return {
5
+ name: "send_message",
6
+ label: "Send message",
7
+ description: "Send a message on one of this stage's declared communication channels. The recipient is fixed by Stageflow configuration and cannot be chosen. Pass the channel alias when the stage declares more than one. Reuse the same operationKey when retrying the same message. Acceptance means provider submission, not delivery or that anyone read it. Never retry an unknown outcome with a new key. Do not put secrets in a message.",
8
+ parameters: Type.Object({
9
+ channel: Type.Optional(Type.String()),
10
+ text: Type.String({ maxLength: MAX_MESSAGE_TEXT }),
11
+ subject: Type.Optional(Type.String()),
12
+ operationKey: Type.String(),
13
+ }),
14
+ async execute(_toolCallId, input) {
15
+ try {
16
+ const receipt = await channels.send(input);
17
+ return { content: [{ type: "text", text: JSON.stringify(receipt) }], details: receipt };
18
+ }
19
+ catch (error) {
20
+ const details = channelFault(error);
21
+ return { content: [{ type: "text", text: JSON.stringify(details) }], details, isError: true };
22
+ }
23
+ },
24
+ };
25
+ }
@@ -1,4 +1,4 @@
1
- import type { LoadedStageConfig, StageBrowserConfig, StageGateKind, StageIoYaml } from "./stage.js";
1
+ import type { LoadedStageConfig, StageChannel, StageBrowserConfig, StageGateKind, StageIoYaml } from "./stage.js";
2
2
  import type { CompletionContract, RecoveryPolicy } from "./completion.js";
3
3
  import type { StageSecretDecl } from "../runtime/stageSecretDecl.js";
4
4
  import type { ToolRequirement } from "../config/toolRequires.js";
@@ -13,6 +13,10 @@ export type PipelineConfig = {
13
13
  schemas?: Record<string, unknown>;
14
14
  /** Declared toolchain binaries this pipeline needs (Slot 9). */
15
15
  requires?: ToolRequirement[];
16
+ /** Default channels inherited by every stage that does not override them. */
17
+ channels?: StageChannel[];
18
+ /** Memory ids every stage in this pipeline can read and replace. */
19
+ memories?: string[];
16
20
  };
17
21
  /** An inline pipeline definition authored directly in a `start_run` call, with no backing file. */
18
22
  export type InlinePipelineDefinition = {
@@ -22,6 +26,8 @@ export type InlinePipelineDefinition = {
22
26
  model?: unknown;
23
27
  schemas?: unknown;
24
28
  requires?: unknown;
29
+ channels?: unknown;
30
+ memories?: unknown;
25
31
  };
26
32
  export type PipelineForkConfig = {
27
33
  select: "one" | "subset";
@@ -36,6 +36,17 @@ export type StageBrowserConfig = {
36
36
  logged_out_url?: string | string[];
37
37
  };
38
38
  };
39
+ export type StageChannelOperation = "send";
40
+ /** A pinned communication target for a stage. Targets are validated per provider. */
41
+ export type StageChannel = {
42
+ alias?: string;
43
+ connection: string;
44
+ operations: StageChannelOperation[];
45
+ to: string | string[];
46
+ cc?: string[];
47
+ /** Provider-specific message template, such as a pinned WhatsApp template. Validated by the provider. */
48
+ template?: Record<string, unknown>;
49
+ };
39
50
  export type StageConfig = {
40
51
  id: string;
41
52
  system_prompt: string;
@@ -56,6 +67,10 @@ export type StageConfig = {
56
67
  operations: ("send" | "reply" | "getMessage" | "search" | "downloadAttachment")[];
57
68
  }[];
58
69
  mcp?: string[];
70
+ /** Communication channels this stage may send on. Inherits pipeline `channels` defaults. */
71
+ channels?: StageChannel[];
72
+ /** Memory ids copied from the pipeline at load. Not a stage YAML key. */
73
+ memories?: string[];
59
74
  /** Declared Host secret names this stage may receive (Slot 6). */
60
75
  secrets?: StageSecretDecl[];
61
76
  /** Declared toolchain binaries this stage needs (Slot 9). */