@pikku/core 0.12.78 → 0.12.80

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 (341) hide show
  1. package/CHANGELOG.md +234 -0
  2. package/dist/dev/hot-reload.js +1 -6
  3. package/dist/ecosystem.d.ts +27 -0
  4. package/dist/ecosystem.js +26 -0
  5. package/dist/errors/error-handler.js +4 -2
  6. package/dist/function/function-runner.js +20 -42
  7. package/dist/function/functions.types.d.ts +9 -5
  8. package/dist/index.d.ts +4 -9
  9. package/dist/index.js +3 -8
  10. package/dist/middleware/auth-cookie.d.ts +0 -4
  11. package/dist/middleware/auth-cookie.js +38 -2
  12. package/dist/middleware/cors.js +1 -0
  13. package/dist/middleware/index.d.ts +1 -1
  14. package/dist/middleware/index.js +1 -1
  15. package/dist/middleware/remote-auth.js +14 -3
  16. package/dist/permissions.d.ts +8 -10
  17. package/dist/permissions.js +0 -11
  18. package/dist/pikku-state.js +12 -5
  19. package/dist/schema.js +35 -1
  20. package/dist/services/ai-run-state-service.d.ts +7 -1
  21. package/dist/services/in-memory-ai-run-state-service.d.ts +1 -1
  22. package/dist/services/in-memory-ai-run-state-service.js +2 -1
  23. package/dist/services/in-memory-workflow-service.d.ts +10 -0
  24. package/dist/services/in-memory-workflow-service.js +25 -0
  25. package/dist/services/local-content-request-handler.d.ts +21 -0
  26. package/dist/services/local-content-request-handler.js +72 -53
  27. package/dist/services/local-content.d.ts +6 -0
  28. package/dist/services/local-content.js +14 -1
  29. package/dist/services/workflow-service.d.ts +4 -2
  30. package/dist/testing/service-tests/agent-run-service-tests.d.ts +10 -0
  31. package/dist/testing/service-tests/agent-run-service-tests.js +72 -0
  32. package/dist/testing/service-tests/ai-storage-service-tests.d.ts +3 -0
  33. package/dist/testing/service-tests/ai-storage-service-tests.js +226 -0
  34. package/dist/testing/service-tests/channel-store-tests.d.ts +3 -0
  35. package/dist/testing/service-tests/channel-store-tests.js +72 -0
  36. package/dist/testing/service-tests/credential-service-tests.d.ts +3 -0
  37. package/dist/testing/service-tests/credential-service-tests.js +109 -0
  38. package/dist/testing/service-tests/deployment-service-tests.d.ts +3 -0
  39. package/dist/testing/service-tests/deployment-service-tests.js +21 -0
  40. package/dist/testing/service-tests/event-hub-store-tests.d.ts +3 -0
  41. package/dist/testing/service-tests/event-hub-store-tests.js +34 -0
  42. package/dist/testing/service-tests/secret-service-tests.d.ts +3 -0
  43. package/dist/testing/service-tests/secret-service-tests.js +80 -0
  44. package/dist/testing/service-tests/session-store-tests.d.ts +3 -0
  45. package/dist/testing/service-tests/session-store-tests.js +43 -0
  46. package/dist/testing/service-tests/workflow-run-service-tests.d.ts +3 -0
  47. package/dist/testing/service-tests/workflow-run-service-tests.js +42 -0
  48. package/dist/testing/service-tests/workflow-service-tests.d.ts +3 -0
  49. package/dist/testing/service-tests/workflow-service-tests.js +150 -0
  50. package/dist/testing/service-tests.d.ts +6 -0
  51. package/dist/testing/service-tests.js +26 -791
  52. package/dist/types/core.types.d.ts +11 -1
  53. package/dist/types/state.types.d.ts +1 -1
  54. package/dist/utils/node-host-resolver.d.ts +12 -0
  55. package/dist/utils/node-host-resolver.js +16 -0
  56. package/dist/utils/safe-fetch.d.ts +18 -0
  57. package/dist/utils/safe-fetch.js +167 -29
  58. package/dist/wirings/actor-flow/run-conversation.js +1 -6
  59. package/dist/wirings/ai-agent/agent-rpc.d.ts +15 -0
  60. package/dist/wirings/ai-agent/agent-rpc.js +53 -0
  61. package/dist/wirings/ai-agent/ai-agent-agui.js +1 -5
  62. package/dist/wirings/ai-agent/ai-agent-memory.js +3 -1
  63. package/dist/wirings/ai-agent/ai-agent-prepare.js +3 -9
  64. package/dist/wirings/ai-agent/ai-agent-runner.js +28 -107
  65. package/dist/wirings/ai-agent/ai-agent-stream.js +20 -61
  66. package/dist/wirings/ai-agent/ai-agent-turn.d.ts +56 -0
  67. package/dist/wirings/ai-agent/ai-agent-turn.js +81 -0
  68. package/dist/wirings/ai-agent/ai-agent.types.d.ts +1 -1
  69. package/dist/wirings/ai-agent/voice-input.js +1 -6
  70. package/dist/wirings/ai-agent/voice-output.js +2 -12
  71. package/dist/wirings/channel/channel-common.js +1 -0
  72. package/dist/wirings/channel/channel-handler.js +3 -5
  73. package/dist/wirings/channel/channel-rpc-service.d.ts +0 -6
  74. package/dist/wirings/channel/channel-rpc-service.js +0 -8
  75. package/dist/wirings/channel/channel-rpc.types.d.ts +6 -0
  76. package/dist/wirings/channel/channel-rpc.types.js +8 -0
  77. package/dist/wirings/channel/channel-runner.d.ts +1 -3
  78. package/dist/wirings/channel/channel-runner.js +16 -8
  79. package/dist/wirings/channel/channel.types.d.ts +2 -0
  80. package/dist/wirings/channel/pikku-abstract-channel-handler.js +1 -0
  81. package/dist/wirings/channel/serverless/serverless-channel-runner.js +3 -0
  82. package/dist/wirings/cli/channel/cli-channel-runner.js +2 -0
  83. package/dist/wirings/cli/cli-runner.js +4 -2
  84. package/dist/wirings/cli/cli.types.d.ts +0 -8
  85. package/dist/wirings/cli/command-parser.js +13 -0
  86. package/dist/wirings/gateway/gateway-runner.js +41 -5
  87. package/dist/wirings/http/http-routes.js +2 -0
  88. package/dist/wirings/http/http-runner.d.ts +0 -10
  89. package/dist/wirings/http/http-runner.js +6 -13
  90. package/dist/wirings/http/http.types.d.ts +0 -10
  91. package/dist/wirings/http/index.d.ts +1 -1
  92. package/dist/wirings/http/index.js +1 -1
  93. package/dist/wirings/mcp/mcp-runner.d.ts +0 -7
  94. package/dist/wirings/mcp/mcp-runner.js +0 -6
  95. package/dist/wirings/rpc/rpc-runner.d.ts +8 -51
  96. package/dist/wirings/rpc/rpc-runner.js +53 -86
  97. package/dist/wirings/rpc/rpc-types.d.ts +3 -0
  98. package/dist/wirings/secret/validate-secret-definitions.js +2 -0
  99. package/dist/wirings/trigger/pikku-trigger-service.d.ts +0 -4
  100. package/dist/wirings/trigger/trigger-runner.js +1 -0
  101. package/dist/wirings/virtual-user/run-virtual-user.js +11 -11
  102. package/dist/wirings/virtual-user/virtual-user-derive.js +4 -25
  103. package/dist/wirings/virtual-user/virtual-user-dispositions.js +1 -4
  104. package/dist/wirings/workflow/dsl/workflow-dsl.types.d.ts +29 -2
  105. package/dist/wirings/workflow/feature.js +7 -4
  106. package/dist/wirings/workflow/graph/graph-runner.d.ts +1 -2
  107. package/dist/wirings/workflow/graph/graph-runner.js +8 -7
  108. package/dist/wirings/workflow/graph/workflow-graph.types.d.ts +0 -4
  109. package/dist/wirings/workflow/index.d.ts +7 -2
  110. package/dist/wirings/workflow/index.js +5 -1
  111. package/dist/wirings/workflow/pikku-scenario-service.d.ts +17 -3
  112. package/dist/wirings/workflow/pikku-scenario-service.js +38 -10
  113. package/dist/wirings/workflow/pikku-workflow-service.d.ts +44 -111
  114. package/dist/wirings/workflow/pikku-workflow-service.js +86 -404
  115. package/dist/wirings/workflow/workflow-approval.d.ts +39 -0
  116. package/dist/wirings/workflow/workflow-approval.js +114 -0
  117. package/dist/wirings/workflow/workflow-constants.d.ts +26 -0
  118. package/dist/wirings/workflow/workflow-constants.js +35 -0
  119. package/dist/wirings/workflow/workflow-errors.d.ts +58 -0
  120. package/dist/wirings/workflow/workflow-errors.js +112 -0
  121. package/dist/wirings/workflow/workflow-meta-resolver.d.ts +11 -0
  122. package/dist/wirings/workflow/workflow-meta-resolver.js +31 -0
  123. package/dist/wirings/workflow/workflow-queue-routing.d.ts +8 -0
  124. package/dist/wirings/workflow/workflow-queue-routing.js +38 -0
  125. package/dist/wirings/workflow/workflow-queue-wiring.d.ts +20 -0
  126. package/dist/wirings/workflow/workflow-queue-wiring.js +79 -0
  127. package/dist/wirings/workflow/workflow-recovery.d.ts +68 -0
  128. package/dist/wirings/workflow/workflow-recovery.js +101 -0
  129. package/dist/wirings/workflow/workflow-run-engine.types.d.ts +54 -0
  130. package/dist/wirings/workflow/workflow-run-engine.types.js +1 -0
  131. package/dist/wirings/workflow/workflow-run-ownership.d.ts +16 -0
  132. package/dist/wirings/workflow/workflow-run-ownership.js +29 -0
  133. package/dist/wirings/workflow/workflow-suspend.d.ts +12 -0
  134. package/dist/wirings/workflow/workflow-suspend.js +33 -0
  135. package/dist/wirings/workflow/workflow.types.d.ts +7 -0
  136. package/knowledge/decisions/internals/a-non-streaming-agent-run-registers-with-airunstate-too.md +22 -0
  137. package/knowledge/decisions/internals/a-resumed-agent-turn-is-as-interruptible-as-the-first.md +20 -0
  138. package/knowledge/decisions/internals/a-scenario-step-template-is-offered-unfilled.md +21 -0
  139. package/knowledge/decisions/internals/a-virtual-user-decides-whether-to-trust-memory-once-per-turn.md +21 -0
  140. package/knowledge/decisions/internals/a-wall-clock-threshold-is-a-load-test-in-disguise.md +46 -0
  141. package/knowledge/decisions/internals/a-workflow-wire-is-built-from-the-run-not-from-the-rpc-service.md +45 -0
  142. package/knowledge/decisions/internals/agent-context-waits-for-a-tool-result-still-being-written.md +21 -0
  143. package/knowledge/decisions/internals/agent-speech-travels-as-a-custom-agui-event.md +22 -0
  144. package/knowledge/decisions/internals/an-agent-interrupt-is-not-a-failure.md +23 -0
  145. package/knowledge/decisions/internals/an-agent-run-owned-by-another-instance-says-so.md +25 -0
  146. package/knowledge/decisions/internals/an-agent-stream-send-must-return-the-inner-sends-promise.md +22 -0
  147. package/knowledge/decisions/internals/an-empty-text-part-is-omitted-from-an-agent-message.md +20 -0
  148. package/knowledge/decisions/internals/an-empty-transcript-is-not-recorded.md +22 -0
  149. package/knowledge/decisions/internals/an-unref-d-timer-cannot-be-awaited-under-node-test.md +66 -0
  150. package/knowledge/decisions/internals/channel-state-accessors-are-unsound-generics-that-every-implementation-asserts.md +33 -0
  151. package/knowledge/decisions/internals/gateway-listener-middleware-runs-without-an-rpc-on-the-wire.md +43 -0
  152. package/knowledge/decisions/internals/hot-reload-writes-into-the-function-map-captured-at-startup.md +26 -0
  153. package/knowledge/decisions/internals/index.md +38 -26
  154. package/knowledge/decisions/internals/only-exposed-functions-enter-a-virtual-user-catalogue.md +21 -0
  155. package/knowledge/decisions/internals/scenario-given-and-when-are-sugar-but-then-is-not.md +24 -0
  156. package/knowledge/decisions/internals/side-effects-are-an-allowlist-not-a-boolean.md +34 -0
  157. package/knowledge/decisions/internals/speech-synthesis-picks-a-voice-per-sentence-and-warns-once.md +24 -0
  158. package/knowledge/decisions/internals/the-actor-prompt-says-json-because-of-json-object-mode.md +22 -0
  159. package/knowledge/decisions/internals/the-agent-done-event-goes-through-the-middleware-and-is-awaited.md +26 -0
  160. package/knowledge/decisions/internals/the-api-report-pins-members-not-just-names.md +43 -0
  161. package/knowledge/decisions/internals/the-ecosystem-entry-point-carries-the-adapter-surface.md +58 -0
  162. package/knowledge/decisions/internals/the-middleware-resolution-cache-is-deliberately-unbounded.md +40 -0
  163. package/knowledge/decisions/internals/the-per-invocation-rpc-view-is-a-class.md +40 -0
  164. package/knowledge/decisions/internals/the-persona-runtime-is-exported-from-the-persona-entry-point.md +28 -0
  165. package/knowledge/decisions/internals/the-transcript-event-is-sent-ahead-of-the-run.md +25 -0
  166. package/knowledge/decisions/internals/the-virtual-user-catalogue-is-the-only-gate-on-what-may-be-called.md +21 -0
  167. package/knowledge/decisions/internals/the-worker-disposition-is-the-one-that-is-not-testing.md +22 -0
  168. package/knowledge/decisions/internals/thread-history-records-the-transcript-not-the-audio.md +25 -0
  169. package/knowledge/decisions/internals/virtual-user-step-order-comes-from-insertion-order.md +21 -0
  170. package/knowledge/decisions/internals/voice-output-speaks-unless-voice-input-explicitly-says-otherwise.md +24 -0
  171. package/knowledge/decisions/internals/wiring-registries-erase-the-generics-their-wire-functions-capture.md +35 -0
  172. package/knowledge/decisions/security/a-dropped-audit-write-is-always-logged.md +4 -2
  173. package/knowledge/decisions/security/a-graph-run-starts-at-an-entry-node-the-graph-declared.md +33 -0
  174. package/knowledge/decisions/security/a-permission-gets-a-wire-it-cannot-reply-on.md +33 -0
  175. package/knowledge/decisions/security/a-step-runs-the-function-the-workflow-dispatched-it-with.md +37 -0
  176. package/knowledge/decisions/security/a-virtual-user-is-never-offered-a-step-that-would-forge-its-own-oracle.md +28 -0
  177. package/knowledge/decisions/security/a-workflow-run-is-read-and-approved-by-its-owner.md +34 -0
  178. package/knowledge/decisions/security/an-agent-approval-is-claimed-before-the-tool-runs.md +33 -0
  179. package/knowledge/decisions/security/an-upload-is-counted-as-it-arrives-not-buffered-then-measured.md +24 -0
  180. package/knowledge/decisions/security/gateway-handlers-run-through-the-function-runner-gate.md +13 -3
  181. package/knowledge/decisions/security/index.md +7 -0
  182. package/knowledge/questions/channel-middleware-accepts-bare-factories-that-nothing-resolves.md +35 -0
  183. package/knowledge/questions/index.md +2 -1
  184. package/knowledge/questions/unauthorized-channel-replies-escape-the-declared-out-type.md +44 -0
  185. package/package.json +14 -3
  186. package/scripts/generate-api-report.d.mts +1 -0
  187. package/scripts/generate-api-report.mjs +89 -0
  188. package/scripts/generate-api-report.mts +218 -0
  189. package/src/api-report.test.ts +69 -0
  190. package/src/column-form.ts +1 -4
  191. package/src/crypto-utils.test.ts +15 -2
  192. package/src/dev/hot-reload.ts +2 -7
  193. package/src/ecosystem.ts +40 -0
  194. package/src/errors/error-handler.ts +5 -3
  195. package/src/errors/error.test.ts +4 -1
  196. package/src/function/function-runner.test.ts +1 -1
  197. package/src/function/function-runner.ts +28 -39
  198. package/src/function/functions.types.ts +15 -9
  199. package/src/handle-error.ts +1 -1
  200. package/src/index.ts +3 -22
  201. package/src/middleware/auth-cookie.test.ts +50 -0
  202. package/src/middleware/auth-cookie.ts +38 -2
  203. package/src/middleware/cors.ts +2 -1
  204. package/src/middleware/index.ts +1 -1
  205. package/src/middleware/remote-auth.test.ts +43 -0
  206. package/src/middleware/remote-auth.ts +17 -3
  207. package/src/middleware-runner.ts +4 -2
  208. package/src/no-any-casts.test.ts +57 -0
  209. package/src/permissions.test.ts +3 -1
  210. package/src/permissions.ts +22 -24
  211. package/src/pikku-state.ts +17 -6
  212. package/src/public-surface.json +578 -0
  213. package/src/public-surface.json.README +25 -0
  214. package/src/public-surface.test.ts +105 -0
  215. package/src/removed-legacy-exports.test.ts +62 -0
  216. package/src/schema.test.ts +78 -0
  217. package/src/schema.ts +36 -1
  218. package/src/services/ai-run-state-service.ts +7 -1
  219. package/src/services/audit-service.ts +2 -2
  220. package/src/services/in-memory-ai-run-state-service.ts +3 -2
  221. package/src/services/in-memory-workflow-service.ts +25 -0
  222. package/src/services/index.ts +1 -4
  223. package/src/services/local-content-request-handler.test.ts +43 -5
  224. package/src/services/local-content-request-handler.ts +103 -74
  225. package/src/services/local-content.ts +15 -1
  226. package/src/services/local-email-service.ts +5 -1
  227. package/src/services/system-role-guard.test.ts +4 -1
  228. package/src/services/workflow-service.ts +9 -2
  229. package/src/side-effects-are-declared.test.ts +84 -0
  230. package/src/source-files-stay-composable.test.ts +41 -0
  231. package/src/testing/service-tests/agent-run-service-tests.ts +98 -0
  232. package/src/testing/service-tests/ai-storage-service-tests.ts +286 -0
  233. package/src/testing/service-tests/channel-store-tests.ts +98 -0
  234. package/src/testing/service-tests/credential-service-tests.ts +143 -0
  235. package/src/testing/service-tests/deployment-service-tests.ts +33 -0
  236. package/src/testing/service-tests/event-hub-store-tests.ts +48 -0
  237. package/src/testing/service-tests/secret-service-tests.ts +105 -0
  238. package/src/testing/service-tests/session-store-tests.ts +62 -0
  239. package/src/testing/service-tests/workflow-run-service-tests.ts +59 -0
  240. package/src/testing/service-tests/workflow-service-tests.ts +308 -0
  241. package/src/testing/service-tests.ts +31 -1111
  242. package/src/types/core.types.ts +15 -1
  243. package/src/types/state.types.ts +1 -1
  244. package/src/utils/node-host-resolver.ts +20 -0
  245. package/src/utils/safe-fetch.test.ts +143 -1
  246. package/src/utils/safe-fetch.ts +200 -25
  247. package/src/wirings/actor-flow/run-conversation.ts +1 -6
  248. package/src/wirings/ai-agent/agent-rpc.ts +120 -0
  249. package/src/wirings/ai-agent/ai-agent-agui.ts +1 -5
  250. package/src/wirings/ai-agent/ai-agent-interrupt.test.ts +2 -1
  251. package/src/wirings/ai-agent/ai-agent-memory.ts +8 -1
  252. package/src/wirings/ai-agent/ai-agent-prepare.ts +10 -12
  253. package/src/wirings/ai-agent/ai-agent-resume-authorization.test.ts +1 -0
  254. package/src/wirings/ai-agent/ai-agent-runner.test.ts +82 -2
  255. package/src/wirings/ai-agent/ai-agent-runner.ts +49 -120
  256. package/src/wirings/ai-agent/ai-agent-stream.test.ts +2 -0
  257. package/src/wirings/ai-agent/ai-agent-stream.ts +36 -63
  258. package/src/wirings/ai-agent/ai-agent-thread-ownership.test.ts +1 -1
  259. package/src/wirings/ai-agent/ai-agent-turn.ts +121 -0
  260. package/src/wirings/ai-agent/ai-agent.types.ts +1 -1
  261. package/src/wirings/ai-agent/voice-input.ts +1 -6
  262. package/src/wirings/ai-agent/voice-output.ts +2 -12
  263. package/src/wirings/channel/channel-common.ts +5 -2
  264. package/src/wirings/channel/channel-handler-shapes.test.ts +72 -0
  265. package/src/wirings/channel/channel-handler.ts +7 -7
  266. package/src/wirings/channel/channel-rpc-service.ts +0 -14
  267. package/src/wirings/channel/channel-rpc.test.ts +25 -4
  268. package/src/wirings/channel/channel-rpc.types.ts +14 -0
  269. package/src/wirings/channel/channel-runner.ts +33 -20
  270. package/src/wirings/channel/channel.types.ts +2 -0
  271. package/src/wirings/channel/local/local-channel-runner.ts +1 -1
  272. package/src/wirings/channel/pikku-abstract-channel-handler.ts +2 -1
  273. package/src/wirings/channel/serverless/serverless-channel-runner.ts +6 -3
  274. package/src/wirings/cli/channel/cli-channel-runner.ts +3 -1
  275. package/src/wirings/cli/channel/cli-raw-client-runner.ts +4 -1
  276. package/src/wirings/cli/cli-runner.ts +7 -4
  277. package/src/wirings/cli/cli.types.ts +0 -39
  278. package/src/wirings/cli/command-parser.test.ts +19 -0
  279. package/src/wirings/cli/command-parser.ts +17 -1
  280. package/src/wirings/gateway/gateway-authorization.test.ts +131 -0
  281. package/src/wirings/gateway/gateway-channel-meta.test.ts +44 -0
  282. package/src/wirings/gateway/gateway-runner.ts +62 -22
  283. package/src/wirings/http/http-routes.ts +4 -1
  284. package/src/wirings/http/http-runner.ts +11 -26
  285. package/src/wirings/http/http.types.ts +0 -15
  286. package/src/wirings/http/index.ts +1 -7
  287. package/src/wirings/http/pikku-fetch-http-request.ts +2 -2
  288. package/src/wirings/http/web-request.ts +1 -1
  289. package/src/wirings/mcp/mcp-runner.ts +2 -16
  290. package/src/wirings/persona/persona-environments.test.ts +14 -3
  291. package/src/wirings/persona/persona.test.ts +13 -3
  292. package/src/wirings/persona/validate-personas.ts +5 -1
  293. package/src/wirings/queue/queue-runner.ts +1 -1
  294. package/src/wirings/rpc/addon-auth-tags.test.ts +1 -5
  295. package/src/wirings/rpc/rpc-runner.ts +58 -136
  296. package/src/wirings/rpc/rpc-types.ts +7 -0
  297. package/src/wirings/rpc/wire-addon.ts +3 -1
  298. package/src/wirings/secret/validate-secret-definitions.test.ts +69 -0
  299. package/src/wirings/secret/validate-secret-definitions.ts +2 -0
  300. package/src/wirings/trigger/pikku-trigger-service.ts +0 -5
  301. package/src/wirings/trigger/trigger-runner.ts +7 -5
  302. package/src/wirings/virtual-user/run-virtual-user.test.ts +18 -9
  303. package/src/wirings/virtual-user/run-virtual-user.ts +28 -15
  304. package/src/wirings/virtual-user/virtual-user-agents.test.ts +4 -1
  305. package/src/wirings/virtual-user/virtual-user-derive.ts +4 -25
  306. package/src/wirings/virtual-user/virtual-user-dispositions.test.ts +7 -2
  307. package/src/wirings/virtual-user/virtual-user-dispositions.ts +1 -4
  308. package/src/wirings/virtual-user/virtual-user-intents.test.ts +13 -3
  309. package/src/wirings/workflow/dsl/workflow-dsl.types.ts +35 -2
  310. package/src/wirings/workflow/feature.ts +7 -4
  311. package/src/wirings/workflow/graph/graph-node.ts +1 -1
  312. package/src/wirings/workflow/graph/graph-runner.test.ts +4 -2
  313. package/src/wirings/workflow/graph/graph-runner.ts +13 -16
  314. package/src/wirings/workflow/graph/workflow-graph.types.ts +0 -5
  315. package/src/wirings/workflow/index.ts +12 -4
  316. package/src/wirings/workflow/pikku-scenario-service.ts +54 -25
  317. package/src/wirings/workflow/pikku-workflow-service.test.ts +2 -2
  318. package/src/wirings/workflow/pikku-workflow-service.ts +208 -630
  319. package/src/wirings/workflow/scenario-hooks.test.ts +51 -0
  320. package/src/wirings/workflow/workflow-approval.ts +185 -0
  321. package/src/wirings/workflow/workflow-child-run-session.test.ts +89 -0
  322. package/src/wirings/workflow/workflow-constants.ts +47 -0
  323. package/src/wirings/workflow/workflow-dispatch-durability.test.ts +1 -1
  324. package/src/wirings/workflow/workflow-dispatch-relay.test.ts +128 -0
  325. package/src/wirings/workflow/workflow-errors.ts +128 -0
  326. package/src/wirings/workflow/workflow-inline-authority.test.ts +12 -6
  327. package/src/wirings/workflow/workflow-meta-resolver.ts +45 -0
  328. package/src/wirings/workflow/workflow-missing-meta.test.ts +92 -0
  329. package/src/wirings/workflow/workflow-queue-routing.ts +85 -0
  330. package/src/wirings/workflow/workflow-queue-wiring.ts +149 -0
  331. package/src/wirings/workflow/workflow-recovery.ts +162 -0
  332. package/src/wirings/workflow/workflow-retry-policy.test.ts +1 -1
  333. package/src/wirings/workflow/workflow-run-authority.test.ts +215 -0
  334. package/src/wirings/workflow/workflow-run-engine.types.ts +91 -0
  335. package/src/wirings/workflow/workflow-run-ownership.ts +36 -0
  336. package/src/wirings/workflow/workflow-suspend.ts +61 -0
  337. package/src/wirings/workflow/workflow.types.ts +7 -0
  338. package/src/wirings-stay-decoupled.test.ts +123 -0
  339. package/tsconfig.json +1 -1
  340. package/tsconfig.tsbuildinfo +1 -1
  341. package/src/internal.ts +0 -10
@@ -5,7 +5,7 @@ import { closeWireServices } from '../../utils.js';
5
5
  import { PikkuError, addError } from '../../errors/error-handler.js';
6
6
  import { InMemoryWorkflowService } from '../../services/in-memory-workflow-service.js';
7
7
  import { runScheduledTask } from '../scheduler/scheduler-runner.js';
8
- import { WorkflowStepNameNotString, } from './pikku-workflow-service.js';
8
+ import { WorkflowStepNameNotString } from './workflow-errors.js';
9
9
  import { resolveScenarioSurfaces, witnessesAgree } from './scenario-surface.js';
10
10
  /**
11
11
  * A workflow service with the scenario capability attached — the two lines
@@ -176,6 +176,10 @@ export class PikkuScenarioService {
176
176
  // Scenario actors per run: live authenticated clients (cookie jars) are
177
177
  // process-local by nature, so they ride this map, never the persisted wire.
178
178
  runActors = new Map();
179
+ // What each run has accumulated so far. Process-local like the actors above:
180
+ // a scenario is a single in-process run, so the body and its hooks share one
181
+ // object rather than reading it back off the persisted wire.
182
+ runContexts = new Map();
179
183
  scenarioBrowserProvider;
180
184
  scenarioEnvironment;
181
185
  runSurface = 'default';
@@ -222,9 +226,35 @@ export class PikkuScenarioService {
222
226
  if (actors) {
223
227
  this.runActors.set(runId, actors);
224
228
  }
229
+ if (workflowMeta.source === 'scenario') {
230
+ this.runContexts.set(runId, {});
231
+ }
225
232
  }
226
233
  detachRunContext(runId) {
227
234
  this.runActors.delete(runId);
235
+ this.runContexts.delete(runId);
236
+ }
237
+ /**
238
+ * What the run has accumulated, for a reporter that wants to say what a
239
+ * failed scenario left behind. Undefined for a plain workflow.
240
+ */
241
+ getRunContext(runId) {
242
+ return this.runContexts.get(runId);
243
+ }
244
+ /**
245
+ * The run's context, created on demand.
246
+ *
247
+ * `attachRunContext` seeds it for an ordinary scenario run, but the wire is
248
+ * also built on paths that skip attach; without this the body would be
249
+ * writing to an `undefined` and teardown would read nothing.
250
+ */
251
+ contextForRun(runId) {
252
+ let runContext = this.runContexts.get(runId);
253
+ if (!runContext) {
254
+ runContext = {};
255
+ this.runContexts.set(runId, runContext);
256
+ }
257
+ return runContext;
228
258
  }
229
259
  decorateRunWire(wire, context) {
230
260
  wire.scenario =
@@ -367,6 +397,10 @@ export class PikkuScenarioService {
367
397
  rpcService,
368
398
  });
369
399
  Object.assign(workflowWire, {
400
+ // One object per run, resolved through the map rather than created here,
401
+ // so the body and its before/after hooks share the same scratch even
402
+ // though the hooks are separate functions that cannot see its locals.
403
+ context: this.contextForRun(runId),
370
404
  // Durable polling step: invoke an RPC (as an actor when options.as is
371
405
  // set) until the predicate passes or `within` elapses. The whole poll is
372
406
  // ONE recorded step, so replay returns the cached outcome.
@@ -451,12 +485,7 @@ export class PikkuScenarioService {
451
485
  }
452
486
  }, options);
453
487
  },
454
- // Scenario steps: a named `pikkuScenarioStep` run as one durable step.
455
- // `given`/`when` are sugar for each other, differing only in the
456
- // prose a reporter renders. `then` is not: the phase is what decides
457
- // whether the step's bindings are alternatives or witnesses, so the same
458
- // step function called two ways runs differently. See
459
- // {@link resolveScenarioSurfaces}.
488
+ // knowledge: decisions/internals/scenario-given-and-when-are-sugar-but-then-is-not.md
460
489
  given: (stepName, stepFunc, data, options) => this.scenarioStep('given', scenarioStepContext(), stepName, stepFunc, data, options),
461
490
  when: (stepName, stepFunc, data, options) => this.scenarioStep('when', scenarioStepContext(), stepName, stepFunc, data, options),
462
491
  then: (stepName, stepFunc, data, options) => this.scenarioStep('then', scenarioStepContext(), stepName, stepFunc, data, options),
@@ -466,7 +495,7 @@ export class PikkuScenarioService {
466
495
  });
467
496
  }
468
497
  async scenarioStep(phase, context, stepName, stepFunc, data, options) {
469
- const { runId, workflowName, addonNamespace, workflowWire, rpcService } = context;
498
+ const { runId, workflowName, addonNamespace, workflowWire } = context;
470
499
  // Also the guard for `then` being a wire member: an accidental
471
500
  // `await scenario` calls it with a resolve function, which lands here as a
472
501
  // loud, named error instead of a silent hang.
@@ -486,11 +515,10 @@ export class PikkuScenarioService {
486
515
  const resolution = resolveScenarioSurfaces(phase, declared, this.runSurface);
487
516
  return await this.engine.inlineStep(runId, stepName, async () => {
488
517
  const runOnSurface = async (surface) => {
518
+ // No `rpc` yet — runPikkuFunc attaches it lazily for the invocation.
489
519
  const wire = {
490
520
  workflow: workflowWire,
491
521
  scenario: workflowWire,
492
- rpc: rpcService?.wire?.rpc,
493
- session: rpcService?.wire?.session,
494
522
  pikkuUserId: workflowWire.pikkuUserId,
495
523
  actors: this.runActors.get(runId),
496
524
  scenarioStep: {
@@ -1,91 +1,11 @@
1
- import type { PikkuWire, SerializedError } from '../../types/core.types.js';
2
- import type { ApprovalOutcome, CoreWorkflow, PikkuWorkflowWire, StepState, StepStatus, WorkflowPlannedStep, WorkflowRun, WorkflowRunMirror, WorkflowRunStatus, WorkflowRunWire, WorkflowStatus, WorkflowVersionStatus, WorkflowQueueOptions, WorkflowStepOptions } from './workflow.types.js';
1
+ import type { CoreUserSession, SerializedError } from '../../types/core.types.js';
2
+ import type { GroupConcurrencyConfig, JobGroup, JobOptions } from '../queue/queue.types.js';
3
+ import type { PikkuWorkflowWire, StepState, StepStatus, WorkflowPlannedStep, WorkflowRun, WorkflowRunMirror, WorkflowRunStatus, WorkflowRunWire, WorkflowStatus, WorkflowVersionStatus, WorkflowQueueOptions, WorkflowStepOptions } from './workflow.types.js';
3
4
  import type { WorkflowService } from '../../services/workflow-service.js';
4
5
  import type { ScenarioPersonas } from '../../services/personas-service.js';
5
- import { PikkuError } from '../../errors/error-handler.js';
6
+ import type { PikkuRPC } from '../rpc/rpc-types.js';
6
7
  import { type RunTimeline, type ReconstructedRunState } from './run-timeline.js';
7
- import type { GroupConcurrencyConfig, JobGroup, JobOptions } from '../queue/queue.types.js';
8
- export declare const DEFAULT_STEP_RETRIES = 5;
9
- export declare class WorkflowAsyncException extends Error {
10
- readonly runId: string;
11
- readonly stepName: string;
12
- constructor(runId: string, stepName: string);
13
- }
14
- export declare class WorkflowCancelledException extends Error {
15
- readonly runId: string;
16
- readonly reason?: string | undefined;
17
- constructor(runId: string, reason?: string | undefined);
18
- }
19
- export declare class WorkflowSuspendedException extends Error {
20
- readonly runId: string;
21
- readonly reason: string;
22
- constructor(runId: string, reason: string);
23
- }
24
- export declare class WorkflowDispatchException extends Error {
25
- readonly runId: string;
26
- readonly stepName: string;
27
- constructor(runId: string, stepName: string, options?: {
28
- cause?: unknown;
29
- });
30
- }
31
- export declare class WorkflowNotFoundError extends PikkuError {
32
- constructor(name: string);
33
- }
34
- export declare class WorkflowRunNotFoundError extends PikkuError {
35
- constructor(runId: string);
36
- }
37
- export declare class WorkflowRunFailedError extends PikkuError {
38
- payload: {
39
- message?: string;
40
- };
41
- constructor(message?: string);
42
- }
43
- export declare class WorkflowRunCancelledError extends PikkuError {
44
- constructor();
45
- }
46
- export declare class WorkflowApprovalResolvedError extends PikkuError {
47
- payload: {
48
- reason: string;
49
- outcome: ApprovalOutcome<unknown>['status'];
50
- };
51
- constructor(reason: string, outcome: ApprovalOutcome<unknown>['status']);
52
- }
53
- export declare class WorkflowServiceNotInitialized extends Error {
54
- }
55
- export declare class WorkflowStepNameNotString extends Error {
56
- constructor(stepName: any);
57
- }
58
- export interface RunLifecycleContext {
59
- runId: string;
60
- run: WorkflowRun;
61
- workflowMeta: any;
62
- workflow: CoreWorkflow;
63
- wire: PikkuWire;
64
- packageName: string | null;
65
- }
66
- export interface WorkflowRunEngine {
67
- inlineStep(runId: string, logicalStepName: string, fn: Function, stepOptions?: WorkflowStepOptions, data?: any, funcName?: string): Promise<any>;
68
- updateRunStatus(runId: string, status: WorkflowStatus, output?: any, error?: SerializedError): Promise<void>;
69
- onChildWorkflowFailed(run: WorkflowRun, error: unknown): Promise<void>;
70
- verifyStepName(stepName: unknown): void;
71
- }
72
- export interface WorkflowRunExtension {
73
- attachRunContext(runId: string, workflowMeta: any, options?: Record<string, any>): Promise<void>;
74
- detachRunContext(runId: string): void;
75
- decorateRunWire(wire: PikkuWire, context: {
76
- runId: string;
77
- workflowMeta: any;
78
- workflowWire: PikkuWorkflowWire;
79
- }): void;
80
- decorateWorkflowWire(workflowWire: PikkuWorkflowWire, context: {
81
- name: string;
82
- runId: string;
83
- rpcService: any;
84
- addonNamespace?: string | null;
85
- }): void;
86
- onBeforeRunFunc(context: RunLifecycleContext): Promise<void>;
87
- onAfterRunFunc(context: RunLifecycleContext, outcome: 'completed' | 'failed' | 'interrupted', failure: unknown): Promise<void>;
88
- }
8
+ import type { WorkflowRunEngine, WorkflowRunExtension } from './workflow-run-engine.types.js';
89
9
  export declare abstract class PikkuWorkflowService implements WorkflowService {
90
10
  private runExtension?;
91
11
  private runContexts;
@@ -179,23 +99,27 @@ export declare abstract class PikkuWorkflowService implements WorkflowService {
179
99
  */
180
100
  protected findStalledRunIds(_before: Date, _limit: number): Promise<string[]>;
181
101
  /**
182
- * Re-drive runs whose next move was lost, and report which were resumed.
183
- *
184
- * Arming a step is two writes to two systems — the step row, then the queue
185
- * or scheduler job — so a process that dies between them leaves a run that is
186
- * `running` with nothing in flight. Nothing notices: the run parks on a step
187
- * that will never complete and never error, so it neither finishes nor fails.
188
- * (Seen on a `workflow.sleep()`: a deploy restart landed between the sleep
189
- * step's insert and its timer, parking the run permanently.)
102
+ * Runs holding a step that has sat `pending` since before `before`, paired
103
+ * with the step that flagged them.
190
104
  *
191
- * Replay is the recovery `resumeWorkflow` re-orchestrates from persisted
192
- * step state, and every settled step is memoized, so resuming a run that was
193
- * not actually stuck costs an orchestration pass and changes nothing. That
194
- * idempotence is what makes an idle-time heuristic safe here; a run that is
195
- * legitimately mid-sleep is excluded anyway, since its step is `scheduled`.
196
- *
197
- * This is not self-starting. Call it from a scheduled task at whatever
198
- * interval suits the workload.
105
+ * Returns nothing by default so a store that cannot express the query keeps
106
+ * working unchanged and, because it does not opt in, gains no re-dispatches
107
+ * either. A store must have an atomic `withStepLock` before overriding this,
108
+ * or no concurrency for one to exclude: the relay makes duplicate dispatch
109
+ * routine, and the claim in `executeWorkflowStepInner` is what keeps a
110
+ * duplicate from becoming a second execution. `kysely-postgres` and
111
+ * `kysely-mysql` qualify on the lock, `in-memory` on being inline and
112
+ * single-process; `mongodb` and `kysely-sqlite` qualify on neither.
113
+ */
114
+ protected findUndispatchedSteps(_before: Date, _limit: number): Promise<Array<{
115
+ runId: string;
116
+ stepId: string;
117
+ }>>;
118
+ private readonly redispatchBackoff;
119
+ private get sweepDeps();
120
+ /**
121
+ * Re-drive runs whose next move was lost. Not self-starting — call it from a
122
+ * scheduled task at whatever interval suits the workload.
199
123
  */
200
124
  recoverStalledRuns(options?: {
201
125
  stalledAfterMs?: number;
@@ -203,6 +127,17 @@ export declare abstract class PikkuWorkflowService implements WorkflowService {
203
127
  }): Promise<{
204
128
  resumed: string[];
205
129
  }>;
130
+ /**
131
+ * Re-drive steps whose dispatch was lost. Not self-starting — call it from a
132
+ * scheduled task; ~30s suits a queue whose `pending`→`running` latency is
133
+ * well under that.
134
+ */
135
+ relayUndispatchedSteps(options?: {
136
+ undispatchedAfterMs?: number;
137
+ limit?: number;
138
+ }): Promise<{
139
+ redispatched: string[];
140
+ }>;
206
141
  protected resolveStepJobOptions(stepOptions?: WorkflowStepOptions): JobOptions;
207
142
  queueStepWorker(runId: string, stepName: string, rpcName: string, data: any, stepOptions?: WorkflowStepOptions, fromStepName?: string): Promise<void>;
208
143
  executeWorkflowSleepCompleted(runId: string, stepId: string): Promise<void>;
@@ -211,7 +146,7 @@ export declare abstract class PikkuWorkflowService implements WorkflowService {
211
146
  protected scheduleSleep(runId: string, stepId: string, duration: number | string): Promise<boolean>;
212
147
  setRunExtension<T extends WorkflowRunExtension>(create: (engine: WorkflowRunEngine) => T): T;
213
148
  getRunExtension(): WorkflowRunExtension | undefined;
214
- startWorkflow<I>(name: string, input: I, wire: WorkflowRunWire, rpcService: any, options?: {
149
+ startWorkflow<I>(name: string, input: I, wire: WorkflowRunWire, rpcService: PikkuRPC, options?: {
215
150
  inline?: boolean;
216
151
  startNode?: string;
217
152
  actors?: ScenarioPersonas;
@@ -219,7 +154,7 @@ export declare abstract class PikkuWorkflowService implements WorkflowService {
219
154
  }): Promise<{
220
155
  runId: string;
221
156
  }>;
222
- runToCompletion<I>(name: string, input: I, rpcService: any, options?: {
157
+ runToCompletion<I>(name: string, input: I, rpcService: PikkuRPC, options?: {
223
158
  pollIntervalMs?: number;
224
159
  wire?: WorkflowRunWire;
225
160
  }): Promise<any>;
@@ -234,14 +169,14 @@ export declare abstract class PikkuWorkflowService implements WorkflowService {
234
169
  private getRunIdentity;
235
170
  private lastStepName;
236
171
  private nextStepKey;
237
- runWorkflowJob(runId: string, rpcService: any): Promise<void>;
172
+ runWorkflowJob(runId: string, rpcService: PikkuRPC): Promise<void>;
238
173
  private runWorkflowJobInner;
239
174
  private onChildWorkflowCompleted;
240
175
  protected onChildWorkflowFailed(childRun: WorkflowRun, error: Error): Promise<void>;
241
176
  private runVersionMismatchFallback;
242
- executeWorkflowStep(runId: string, stepName: string, rpcName: string, data: any, rpcService: any): Promise<void>;
177
+ executeWorkflowStep(runId: string, stepName: string, rpcName: string, data: any, rpcService: PikkuRPC): Promise<void>;
243
178
  private executeWorkflowStepInner;
244
- orchestrateWorkflow(runId: string, rpcService: any): Promise<void>;
179
+ orchestrateWorkflow(runId: string, rpcService: PikkuRPC): Promise<void>;
245
180
  private verifyQueueService;
246
181
  private invokeStepRpc;
247
182
  private runInlineRetryLoop;
@@ -249,14 +184,12 @@ export declare abstract class PikkuWorkflowService implements WorkflowService {
249
184
  private rpcStep;
250
185
  protected inlineStep(runId: string, logicalStepName: string, fn: Function, stepOptions?: WorkflowStepOptions, data?: any, rpcName?: string | null): Promise<any>;
251
186
  private sleepStep;
252
- private getSuspendStepName;
253
187
  private suspendStep;
254
188
  private scheduleRunWake;
255
- private getApprovalStepName;
256
- private approvalStateKey;
257
- approveStep(runId: string, reason: string, decision: unknown): Promise<void>;
189
+ private get approvalStore();
190
+ approveStep(runId: string, reason: string, decision: unknown, session?: CoreUserSession): Promise<void>;
258
191
  private approvalStep;
259
- createWorkflowWire(name: string, runId: string, rpcService: any, addonNamespace?: string | null): PikkuWorkflowWire;
192
+ createWorkflowWire(name: string, runId: string, rpcService: PikkuRPC, addonNamespace?: string | null): PikkuWorkflowWire;
260
193
  protected verifyStepName(stepName: string): void;
261
194
  private getConfig;
262
195
  protected getOrchestratorQueueName(workflowName?: string): string;