@pikku/core 0.12.107 → 0.12.111

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 (588) hide show
  1. package/CHANGELOG.md +344 -0
  2. package/dist/analytics/analytics.d.ts +6 -0
  3. package/dist/analytics/analytics.js +58 -0
  4. package/dist/analytics/analytics.types.d.ts +156 -0
  5. package/dist/analytics/analytics.types.js +1 -0
  6. package/dist/analytics/anonymous-analytics-identity.d.ts +23 -0
  7. package/dist/analytics/anonymous-analytics-identity.js +27 -0
  8. package/dist/analytics/compose-analytics-identity.d.ts +14 -0
  9. package/dist/analytics/compose-analytics-identity.js +33 -0
  10. package/dist/analytics/cookie-analytics-identity.d.ts +24 -0
  11. package/dist/analytics/cookie-analytics-identity.js +37 -0
  12. package/dist/analytics/define-analytics-events.d.ts +22 -0
  13. package/dist/analytics/define-analytics-events.js +9 -0
  14. package/dist/analytics/fan-out-analytics.d.ts +15 -0
  15. package/dist/analytics/fan-out-analytics.js +36 -0
  16. package/dist/analytics/index.d.ts +13 -0
  17. package/dist/analytics/index.js +8 -0
  18. package/dist/analytics/logger-analytics-service.d.ts +14 -0
  19. package/dist/analytics/logger-analytics-service.js +23 -0
  20. package/dist/analytics/mint-cookie.d.ts +44 -0
  21. package/dist/analytics/mint-cookie.js +55 -0
  22. package/dist/errors/errors.d.ts +7 -0
  23. package/dist/errors/errors.js +17 -0
  24. package/dist/function/function-meta.types.d.ts +2 -0
  25. package/dist/function/function-runner.js +29 -0
  26. package/dist/function/functions.types.d.ts +22 -3
  27. package/dist/middleware/auth-apikey.d.ts +1 -1
  28. package/dist/pikku-state.d.ts +1 -1
  29. package/dist/scopes.d.ts +11 -0
  30. package/dist/scopes.js +17 -0
  31. package/dist/services/credential-wire-service.d.ts +1 -1
  32. package/dist/services/feature-flag-service.d.ts +100 -0
  33. package/dist/services/feature-flag-service.js +1 -0
  34. package/dist/services/index.d.ts +1 -0
  35. package/dist/services/meta-service.d.ts +16 -0
  36. package/dist/services/meta-service.js +19 -0
  37. package/dist/services/webhook-service.d.ts +7 -2
  38. package/dist/services/webhook-service.js +11 -6
  39. package/dist/testing/service-tests/agent-run-service-tests.d.ts +2 -2
  40. package/dist/testing/service-tests/agent-storage-service-tests.d.ts +1 -1
  41. package/dist/testing/service-tests/channel-store-tests.d.ts +1 -1
  42. package/dist/testing/service-tests/credential-service-tests.d.ts +1 -1
  43. package/dist/testing/service-tests/deployment-service-tests.d.ts +1 -1
  44. package/dist/testing/service-tests/event-hub-store-tests.d.ts +1 -1
  45. package/dist/testing/service-tests/secret-service-tests.d.ts +1 -1
  46. package/dist/testing/service-tests/session-store-tests.d.ts +1 -1
  47. package/dist/testing/service-tests/workflow-run-service-tests.d.ts +1 -1
  48. package/dist/testing/service-tests/workflow-service-tests.d.ts +1 -1
  49. package/dist/types/core.types.d.ts +23 -0
  50. package/dist/wirings/agent/agent-rpc.d.ts +1 -1
  51. package/dist/wirings/agent/agent-turn.d.ts +1 -1
  52. package/dist/wirings/agent-scorer/agent-scorer-live.d.ts +1 -1
  53. package/dist/wirings/channel/channel-common.d.ts +1 -1
  54. package/dist/wirings/channel/channel-rpc-validators.d.ts +2 -2
  55. package/dist/wirings/channel/channel-runner.d.ts +1 -1
  56. package/dist/wirings/channel/local/local-channel-runner.d.ts +1 -1
  57. package/dist/wirings/channel/serverless/serverless-channel-runner.d.ts +1 -1
  58. package/dist/wirings/cli/channel/cli-approval.d.ts +2 -2
  59. package/dist/wirings/flag/assert-feature-available.d.ts +15 -0
  60. package/dist/wirings/flag/assert-feature-available.js +23 -0
  61. package/dist/wirings/flag/cached-flag-source.d.ts +73 -0
  62. package/dist/wirings/flag/cached-flag-source.js +96 -0
  63. package/dist/wirings/flag/define-feature-flags.d.ts +33 -0
  64. package/dist/wirings/flag/define-feature-flags.js +32 -0
  65. package/dist/wirings/flag/flag.types.d.ts +97 -0
  66. package/dist/wirings/flag/flag.types.js +1 -0
  67. package/dist/wirings/flag/index.d.ts +7 -0
  68. package/dist/wirings/flag/index.js +5 -0
  69. package/dist/wirings/flag/resolve-flag.d.ts +52 -0
  70. package/dist/wirings/flag/resolve-flag.js +90 -0
  71. package/dist/wirings/flag/validate-flag-definitions.d.ts +26 -0
  72. package/dist/wirings/flag/validate-flag-definitions.js +103 -0
  73. package/dist/wirings/virtual-user/virtual-user-scaffold.d.ts +8 -8
  74. package/dist/wirings/virtual-user/virtual-user-schedule.d.ts +1 -1
  75. package/dist/wirings/workflow/workflow-queue-routing.d.ts +1 -1
  76. package/package.json +11 -5
  77. package/run-tests.sh +17 -9
  78. package/src/public-surface.json +26 -0
  79. package/src/agent-naming.test.ts +0 -68
  80. package/src/api-report.test.ts +0 -138
  81. package/src/app-alias-surface.test.ts +0 -179
  82. package/src/app-leaf-surface.test.ts +0 -222
  83. package/src/bootstrap-compat/root.ts +0 -20
  84. package/src/classification/column-form.test.ts +0 -97
  85. package/src/classification/column-form.ts +0 -55
  86. package/src/classification/data-classification.ts +0 -73
  87. package/src/classification/index.ts +0 -40
  88. package/src/classification/key-ids.ts +0 -2
  89. package/src/classification/secret-value.test.ts +0 -204
  90. package/src/classification/secret-value.ts +0 -106
  91. package/src/crypto-utils.test.ts +0 -668
  92. package/src/crypto-utils.ts +0 -460
  93. package/src/dev/hot-reload.test.ts +0 -587
  94. package/src/dev/hot-reload.ts +0 -225
  95. package/src/dev/module-runner.test.ts +0 -235
  96. package/src/dev/module-runner.ts +0 -138
  97. package/src/dev/reload-meta.test.ts +0 -183
  98. package/src/dev/reload-meta.ts +0 -144
  99. package/src/ecosystem-tier-removed.test.ts +0 -72
  100. package/src/env.ts +0 -1
  101. package/src/errors/error-handler.ts +0 -77
  102. package/src/errors/error.test.ts +0 -229
  103. package/src/errors/errors.ts +0 -393
  104. package/src/errors/index.ts +0 -11
  105. package/src/errors/serialized-error.ts +0 -12
  106. package/src/factory-functions.test.ts +0 -111
  107. package/src/function/abort-scope.test.ts +0 -97
  108. package/src/function/abort-scope.ts +0 -80
  109. package/src/function/function-meta.types.ts +0 -151
  110. package/src/function/function-runner.test.ts +0 -1619
  111. package/src/function/function-runner.ts +0 -499
  112. package/src/function/functions.types.ts +0 -319
  113. package/src/function/index.ts +0 -40
  114. package/src/function/list.types.test.ts +0 -100
  115. package/src/function/list.types.ts +0 -69
  116. package/src/function/pikku-request.test.ts +0 -35
  117. package/src/function/pikku-request.ts +0 -17
  118. package/src/gopass-secrets-removed.test.ts +0 -51
  119. package/src/handle-error.test.ts +0 -532
  120. package/src/handle-error.ts +0 -64
  121. package/src/middleware/auth-apikey.test.ts +0 -362
  122. package/src/middleware/auth-apikey.ts +0 -39
  123. package/src/middleware/auth-bearer.test.ts +0 -566
  124. package/src/middleware/auth-bearer.ts +0 -83
  125. package/src/middleware/auth-cookie.test.ts +0 -572
  126. package/src/middleware/auth-cookie.ts +0 -107
  127. package/src/middleware/cors.test.ts +0 -579
  128. package/src/middleware/cors.ts +0 -103
  129. package/src/middleware/index.ts +0 -30
  130. package/src/middleware/middleware-factories.ts +0 -76
  131. package/src/middleware/middleware.types.ts +0 -61
  132. package/src/middleware/remote-auth.test.ts +0 -547
  133. package/src/middleware/remote-auth.ts +0 -95
  134. package/src/middleware/remote-jobs-secret.ts +0 -35
  135. package/src/middleware/require-origin.test.ts +0 -115
  136. package/src/middleware/require-origin.ts +0 -79
  137. package/src/middleware/telemetry.ts +0 -83
  138. package/src/middleware-runner.test.ts +0 -578
  139. package/src/middleware-runner.ts +0 -232
  140. package/src/no-any-casts.test.ts +0 -57
  141. package/src/no-root-barrel.test.ts +0 -122
  142. package/src/permissions.test.ts +0 -256
  143. package/src/permissions.ts +0 -217
  144. package/src/pikku-state.test.ts +0 -198
  145. package/src/pikku-state.ts +0 -206
  146. package/src/production-barrels-stay-lean.test.ts +0 -110
  147. package/src/public-surface.test.ts +0 -133
  148. package/src/remote.test.ts +0 -173
  149. package/src/remote.ts +0 -56
  150. package/src/removed-legacy-exports.test.ts +0 -66
  151. package/src/run-tests-script.test.ts +0 -67
  152. package/src/schema.test.ts +0 -430
  153. package/src/schema.ts +0 -204
  154. package/src/scopes.test.ts +0 -203
  155. package/src/scopes.ts +0 -67
  156. package/src/services/agent-run-state-service.ts +0 -37
  157. package/src/services/agent-runner-service.ts +0 -238
  158. package/src/services/agent-storage-service.ts +0 -39
  159. package/src/services/ai-embedding-service.ts +0 -9
  160. package/src/services/audit-service.test.ts +0 -44
  161. package/src/services/audit-service.ts +0 -280
  162. package/src/services/content-service.ts +0 -65
  163. package/src/services/credential-service.ts +0 -20
  164. package/src/services/credential-wire-service.test.ts +0 -235
  165. package/src/services/credential-wire-service.ts +0 -120
  166. package/src/services/deployment-service.ts +0 -32
  167. package/src/services/email-service.test.ts +0 -100
  168. package/src/services/email-service.ts +0 -60
  169. package/src/services/email-template.test.ts +0 -311
  170. package/src/services/email-template.ts +0 -254
  171. package/src/services/file-scenario-run-store.test.ts +0 -349
  172. package/src/services/file-scenario-run-store.ts +0 -282
  173. package/src/services/gateway-service.ts +0 -5
  174. package/src/services/http-personas-converse.test.ts +0 -274
  175. package/src/services/http-personas.test.ts +0 -379
  176. package/src/services/http-personas.ts +0 -508
  177. package/src/services/in-memory-agent-run-state-service.ts +0 -87
  178. package/src/services/in-memory-queue-service.test.ts +0 -162
  179. package/src/services/in-memory-queue-service.ts +0 -78
  180. package/src/services/in-memory-session-store.test.ts +0 -58
  181. package/src/services/in-memory-session-store.ts +0 -20
  182. package/src/services/in-memory-trigger-service.ts +0 -47
  183. package/src/services/in-memory-workflow-service.test.ts +0 -430
  184. package/src/services/in-memory-workflow-service.ts +0 -595
  185. package/src/services/index.ts +0 -192
  186. package/src/services/istanbul-coverage-service.test.ts +0 -66
  187. package/src/services/istanbul-coverage-service.ts +0 -59
  188. package/src/services/jwt-service.ts +0 -15
  189. package/src/services/local-content-request-handler.test.ts +0 -240
  190. package/src/services/local-content-request-handler.ts +0 -295
  191. package/src/services/local-content.test.ts +0 -186
  192. package/src/services/local-content.ts +0 -242
  193. package/src/services/local-credential-service.ts +0 -63
  194. package/src/services/local-email-service.test.ts +0 -182
  195. package/src/services/local-email-service.ts +0 -43
  196. package/src/services/local-gateway-service.ts +0 -51
  197. package/src/services/local-secrets.test.ts +0 -95
  198. package/src/services/local-secrets.ts +0 -71
  199. package/src/services/local-variables.test.ts +0 -61
  200. package/src/services/local-variables.ts +0 -45
  201. package/src/services/logger-console.test.ts +0 -117
  202. package/src/services/logger-console.ts +0 -174
  203. package/src/services/logger.ts +0 -48
  204. package/src/services/meta-service.test.ts +0 -75
  205. package/src/services/meta-service.ts +0 -767
  206. package/src/services/persona-actor-secret.test.ts +0 -68
  207. package/src/services/persona-actor-secret.ts +0 -70
  208. package/src/services/persona-sign-in.test.ts +0 -219
  209. package/src/services/persona-sign-in.ts +0 -238
  210. package/src/services/personas-service.ts +0 -191
  211. package/src/services/pikku-user-id.test.ts +0 -62
  212. package/src/services/pikku-user-id.ts +0 -13
  213. package/src/services/queue-webhook-service.test.ts +0 -409
  214. package/src/services/queue-webhook-service.ts +0 -150
  215. package/src/services/remote-jobs.test.ts +0 -106
  216. package/src/services/remote-jobs.ts +0 -92
  217. package/src/services/scheduler-service.ts +0 -37
  218. package/src/services/schema-service.ts +0 -10
  219. package/src/services/scope-service.ts +0 -91
  220. package/src/services/scoped-credential-service.test.ts +0 -86
  221. package/src/services/scoped-credential-service.ts +0 -63
  222. package/src/services/scoped-secret-service.test.ts +0 -93
  223. package/src/services/scoped-secret-service.ts +0 -40
  224. package/src/services/secret-host-binding.test.ts +0 -138
  225. package/src/services/secret-host-binding.ts +0 -51
  226. package/src/services/secret-service.ts +0 -25
  227. package/src/services/secretless.test.ts +0 -54
  228. package/src/services/secretless.ts +0 -29
  229. package/src/services/session-store.ts +0 -9
  230. package/src/services/stub-tracker.test.ts +0 -104
  231. package/src/services/stub-tracker.ts +0 -175
  232. package/src/services/system-role-guard.test.ts +0 -96
  233. package/src/services/system-role-guard.ts +0 -71
  234. package/src/services/temporary-file-service.ts +0 -76
  235. package/src/services/trigger-service.ts +0 -5
  236. package/src/services/typed-credential-service.ts +0 -83
  237. package/src/services/typed-secret-service.test.ts +0 -204
  238. package/src/services/typed-secret-service.ts +0 -132
  239. package/src/services/typed-variables-service.test.ts +0 -166
  240. package/src/services/typed-variables-service.ts +0 -166
  241. package/src/services/user-session-service.test.ts +0 -147
  242. package/src/services/user-session-service.ts +0 -85
  243. package/src/services/v8-coverage-service.test.ts +0 -69
  244. package/src/services/v8-coverage-service.ts +0 -163
  245. package/src/services/variables-service.ts +0 -13
  246. package/src/services/webhook-service.ts +0 -147
  247. package/src/services/workflow-service.ts +0 -120
  248. package/src/side-effects-are-declared.test.ts +0 -84
  249. package/src/source-files-stay-composable.test.ts +0 -41
  250. package/src/template-alias-surface.test.ts +0 -240
  251. package/src/test-utils.ts +0 -38
  252. package/src/testing/index.ts +0 -3
  253. package/src/testing/service-tests/agent-run-service-tests.ts +0 -98
  254. package/src/testing/service-tests/agent-storage-service-tests.ts +0 -379
  255. package/src/testing/service-tests/channel-store-tests.ts +0 -98
  256. package/src/testing/service-tests/credential-service-tests.ts +0 -143
  257. package/src/testing/service-tests/deployment-service-tests.ts +0 -33
  258. package/src/testing/service-tests/event-hub-store-tests.ts +0 -48
  259. package/src/testing/service-tests/secret-service-tests.ts +0 -105
  260. package/src/testing/service-tests/session-store-tests.ts +0 -62
  261. package/src/testing/service-tests/workflow-run-service-tests.ts +0 -59
  262. package/src/testing/service-tests/workflow-service-tests.ts +0 -308
  263. package/src/testing/service-tests.ts +0 -95
  264. package/src/time-utils.test.ts +0 -56
  265. package/src/time-utils.ts +0 -89
  266. package/src/types/core.types.ts +0 -446
  267. package/src/types/index.ts +0 -25
  268. package/src/types/state.types.ts +0 -226
  269. package/src/types/typed-credentials.test.ts +0 -72
  270. package/src/utils/hash.test.ts +0 -68
  271. package/src/utils/hash.ts +0 -26
  272. package/src/utils/hmac.ts +0 -21
  273. package/src/utils/node-host-resolver.ts +0 -20
  274. package/src/utils/safe-fetch.test.ts +0 -515
  275. package/src/utils/safe-fetch.ts +0 -347
  276. package/src/utils.test.ts +0 -359
  277. package/src/utils.ts +0 -165
  278. package/src/version.test.ts +0 -80
  279. package/src/version.ts +0 -25
  280. package/src/wirings/actor-flow/actor-flow.types.ts +0 -40
  281. package/src/wirings/actor-flow/index.ts +0 -10
  282. package/src/wirings/actor-flow/run-conversation.test.ts +0 -187
  283. package/src/wirings/actor-flow/run-conversation.ts +0 -280
  284. package/src/wirings/addon/addon-auth-tags.test.ts +0 -219
  285. package/src/wirings/addon/addon-runner.ts +0 -236
  286. package/src/wirings/addon/addon-scopes.test.ts +0 -225
  287. package/src/wirings/addon/addon-secrets.test.ts +0 -391
  288. package/src/wirings/addon/index.ts +0 -12
  289. package/src/wirings/addon/remote-addon-auth.ts +0 -65
  290. package/src/wirings/addon/wire-addon.test.ts +0 -102
  291. package/src/wirings/addon/wire-addon.ts +0 -202
  292. package/src/wirings/addon/wire-remote-addon.ts +0 -41
  293. package/src/wirings/agent/agent-agui.test.ts +0 -1213
  294. package/src/wirings/agent/agent-agui.ts +0 -405
  295. package/src/wirings/agent/agent-authorization.test.ts +0 -208
  296. package/src/wirings/agent/agent-finalize.test.ts +0 -187
  297. package/src/wirings/agent/agent-finalize.ts +0 -197
  298. package/src/wirings/agent/agent-helpers.test.ts +0 -215
  299. package/src/wirings/agent/agent-helpers.ts +0 -96
  300. package/src/wirings/agent/agent-interrupt.test.ts +0 -833
  301. package/src/wirings/agent/agent-interrupt.ts +0 -400
  302. package/src/wirings/agent/agent-memory.test.ts +0 -397
  303. package/src/wirings/agent/agent-memory.ts +0 -496
  304. package/src/wirings/agent/agent-middleware.types.test.ts +0 -41
  305. package/src/wirings/agent/agent-model-config.test.ts +0 -103
  306. package/src/wirings/agent/agent-model-config.ts +0 -59
  307. package/src/wirings/agent/agent-prepare.test.ts +0 -977
  308. package/src/wirings/agent/agent-prepare.ts +0 -1083
  309. package/src/wirings/agent/agent-registry.test.ts +0 -455
  310. package/src/wirings/agent/agent-registry.ts +0 -99
  311. package/src/wirings/agent/agent-resume-authorization.test.ts +0 -206
  312. package/src/wirings/agent/agent-rpc.ts +0 -116
  313. package/src/wirings/agent/agent-runner.test.ts +0 -1229
  314. package/src/wirings/agent/agent-runner.ts +0 -858
  315. package/src/wirings/agent/agent-stream-delegate.test.ts +0 -381
  316. package/src/wirings/agent/agent-stream-output-hooks.test.ts +0 -353
  317. package/src/wirings/agent/agent-stream.test.ts +0 -1800
  318. package/src/wirings/agent/agent-stream.ts +0 -1639
  319. package/src/wirings/agent/agent-thread-ownership.test.ts +0 -297
  320. package/src/wirings/agent/agent-turn.test.ts +0 -65
  321. package/src/wirings/agent/agent-turn.ts +0 -122
  322. package/src/wirings/agent/agent-utils.ts +0 -20
  323. package/src/wirings/agent/agent.types.ts +0 -676
  324. package/src/wirings/agent/index.ts +0 -58
  325. package/src/wirings/agent/voice-input.test.ts +0 -220
  326. package/src/wirings/agent/voice-input.ts +0 -180
  327. package/src/wirings/agent/voice-output.test.ts +0 -510
  328. package/src/wirings/agent/voice-output.ts +0 -311
  329. package/src/wirings/agent-scorer/agent-scorer-grade.test.ts +0 -106
  330. package/src/wirings/agent-scorer/agent-scorer-grade.ts +0 -55
  331. package/src/wirings/agent-scorer/agent-scorer-judge.test.ts +0 -285
  332. package/src/wirings/agent-scorer/agent-scorer-judge.ts +0 -180
  333. package/src/wirings/agent-scorer/agent-scorer-live.test.ts +0 -174
  334. package/src/wirings/agent-scorer/agent-scorer-live.ts +0 -56
  335. package/src/wirings/agent-scorer/agent-scorer-registry.ts +0 -66
  336. package/src/wirings/agent-scorer/agent-scorer-sampling.test.ts +0 -34
  337. package/src/wirings/agent-scorer/agent-scorer-sampling.ts +0 -36
  338. package/src/wirings/agent-scorer/agent-scorer-snapshots.test.ts +0 -49
  339. package/src/wirings/agent-scorer/agent-scorer-snapshots.ts +0 -46
  340. package/src/wirings/agent-scorer/agent-scorer-worker.test.ts +0 -122
  341. package/src/wirings/agent-scorer/agent-scorer-worker.ts +0 -71
  342. package/src/wirings/agent-scorer/agent-scorer.ts +0 -102
  343. package/src/wirings/agent-scorer/agent-scorer.types.ts +0 -128
  344. package/src/wirings/agent-scorer/index.ts +0 -23
  345. package/src/wirings/channel/channel-common.ts +0 -102
  346. package/src/wirings/channel/channel-handler-shapes.test.ts +0 -72
  347. package/src/wirings/channel/channel-handler.test.ts +0 -322
  348. package/src/wirings/channel/channel-handler.ts +0 -259
  349. package/src/wirings/channel/channel-host-rpc.test.ts +0 -150
  350. package/src/wirings/channel/channel-host-rpc.ts +0 -69
  351. package/src/wirings/channel/channel-middleware-runner.test.ts +0 -188
  352. package/src/wirings/channel/channel-middleware-runner.ts +0 -126
  353. package/src/wirings/channel/channel-rpc-registry.ts +0 -116
  354. package/src/wirings/channel/channel-rpc-responder.ts +0 -117
  355. package/src/wirings/channel/channel-rpc-service.ts +0 -132
  356. package/src/wirings/channel/channel-rpc-validators.ts +0 -65
  357. package/src/wirings/channel/channel-rpc.test.ts +0 -841
  358. package/src/wirings/channel/channel-rpc.ts +0 -5
  359. package/src/wirings/channel/channel-rpc.types.ts +0 -160
  360. package/src/wirings/channel/channel-runner.ts +0 -164
  361. package/src/wirings/channel/channel-store.ts +0 -35
  362. package/src/wirings/channel/channel.types.ts +0 -193
  363. package/src/wirings/channel/define-channel-routes.ts +0 -5
  364. package/src/wirings/channel/eventhub-service.ts +0 -16
  365. package/src/wirings/channel/eventhub-store.ts +0 -13
  366. package/src/wirings/channel/index.ts +0 -40
  367. package/src/wirings/channel/local/index.ts +0 -3
  368. package/src/wirings/channel/local/local-channel-handler.ts +0 -98
  369. package/src/wirings/channel/local/local-channel-runner.test.ts +0 -339
  370. package/src/wirings/channel/local/local-channel-runner.ts +0 -271
  371. package/src/wirings/channel/local/local-eventhub-service.test.ts +0 -77
  372. package/src/wirings/channel/local/local-eventhub-service.ts +0 -69
  373. package/src/wirings/channel/log-channels.ts +0 -16
  374. package/src/wirings/channel/pikku-abstract-channel-handler.test.ts +0 -135
  375. package/src/wirings/channel/pikku-abstract-channel-handler.ts +0 -60
  376. package/src/wirings/channel/serverless/index.ts +0 -6
  377. package/src/wirings/channel/serverless/serverless-channel-runner.ts +0 -328
  378. package/src/wirings/cli/channel/cli-approval.test.ts +0 -177
  379. package/src/wirings/cli/channel/cli-approval.ts +0 -135
  380. package/src/wirings/cli/channel/cli-channel-runner.ts +0 -118
  381. package/src/wirings/cli/channel/cli-raw-channel-runner.test.ts +0 -192
  382. package/src/wirings/cli/channel/cli-raw-channel-runner.ts +0 -148
  383. package/src/wirings/cli/channel/cli-raw-client-runner.test.ts +0 -480
  384. package/src/wirings/cli/channel/cli-raw-client-runner.ts +0 -188
  385. package/src/wirings/cli/channel/index.ts +0 -6
  386. package/src/wirings/cli/cli-runner.test.ts +0 -969
  387. package/src/wirings/cli/cli-runner.ts +0 -538
  388. package/src/wirings/cli/cli.types.ts +0 -388
  389. package/src/wirings/cli/command-parser.test.ts +0 -1120
  390. package/src/wirings/cli/command-parser.ts +0 -713
  391. package/src/wirings/cli/define-cli-commands.ts +0 -13
  392. package/src/wirings/cli/format-cli-error.test.ts +0 -91
  393. package/src/wirings/cli/format-cli-error.ts +0 -96
  394. package/src/wirings/cli/index.ts +0 -19
  395. package/src/wirings/credential/credential.types.ts +0 -37
  396. package/src/wirings/credential/define-credential.ts +0 -49
  397. package/src/wirings/credential/index.ts +0 -7
  398. package/src/wirings/credential/validate-credential-definitions.ts +0 -63
  399. package/src/wirings/gateway/gateway-authorization.test.ts +0 -575
  400. package/src/wirings/gateway/gateway-channel-meta.test.ts +0 -44
  401. package/src/wirings/gateway/gateway-runner.test.ts +0 -581
  402. package/src/wirings/gateway/gateway-runner.ts +0 -411
  403. package/src/wirings/gateway/gateway.types.ts +0 -137
  404. package/src/wirings/gateway/index.ts +0 -15
  405. package/src/wirings/http/http-routes.test.ts +0 -318
  406. package/src/wirings/http/http-routes.ts +0 -111
  407. package/src/wirings/http/http-runner-addon-ref.test.ts +0 -238
  408. package/src/wirings/http/http-runner.test.ts +0 -503
  409. package/src/wirings/http/http-runner.ts +0 -462
  410. package/src/wirings/http/http.types.ts +0 -307
  411. package/src/wirings/http/index.ts +0 -27
  412. package/src/wirings/http/log-http-routes.ts +0 -18
  413. package/src/wirings/http/pikku-fetch-http-request.test.ts +0 -318
  414. package/src/wirings/http/pikku-fetch-http-request.ts +0 -260
  415. package/src/wirings/http/pikku-fetch-http-response.test.ts +0 -123
  416. package/src/wirings/http/pikku-fetch-http-response.ts +0 -149
  417. package/src/wirings/http/routers/http-router.ts +0 -13
  418. package/src/wirings/http/routers/path-to-regex.test.ts +0 -306
  419. package/src/wirings/http/routers/path-to-regex.ts +0 -115
  420. package/src/wirings/http/web-request.test.ts +0 -382
  421. package/src/wirings/http/web-request.ts +0 -162
  422. package/src/wirings/mcp/index.ts +0 -26
  423. package/src/wirings/mcp/mcp-endpoint-registry.test.ts +0 -388
  424. package/src/wirings/mcp/mcp-endpoint-registry.ts +0 -159
  425. package/src/wirings/mcp/mcp-runner.test.ts +0 -588
  426. package/src/wirings/mcp/mcp-runner.ts +0 -330
  427. package/src/wirings/mcp/mcp.types.ts +0 -199
  428. package/src/wirings/node/index.ts +0 -2
  429. package/src/wirings/node/node.types.ts +0 -23
  430. package/src/wirings/oauth2/index.ts +0 -1
  431. package/src/wirings/oauth2/oauth2.types.ts +0 -12
  432. package/src/wirings/persona/define-personas.ts +0 -33
  433. package/src/wirings/persona/index.ts +0 -75
  434. package/src/wirings/persona/persona-app-scopes.test.ts +0 -47
  435. package/src/wirings/persona/persona-app-scopes.ts +0 -74
  436. package/src/wirings/persona/persona-email.ts +0 -87
  437. package/src/wirings/persona/persona-environments.test.ts +0 -194
  438. package/src/wirings/persona/persona-environments.ts +0 -138
  439. package/src/wirings/persona/persona-mailbox.ts +0 -156
  440. package/src/wirings/persona/persona.test.ts +0 -230
  441. package/src/wirings/persona/persona.types.ts +0 -156
  442. package/src/wirings/persona/validate-personas.ts +0 -137
  443. package/src/wirings/queue/index.ts +0 -29
  444. package/src/wirings/queue/queue-identity.test.ts +0 -454
  445. package/src/wirings/queue/queue-identity.ts +0 -176
  446. package/src/wirings/queue/queue-runner.test.ts +0 -705
  447. package/src/wirings/queue/queue-runner.ts +0 -181
  448. package/src/wirings/queue/queue.types.ts +0 -161
  449. package/src/wirings/queue/register-queue-helper.ts +0 -46
  450. package/src/wirings/queue/signed-queue-service.ts +0 -60
  451. package/src/wirings/queue/validate-worker-config.test.ts +0 -108
  452. package/src/wirings/queue/validate-worker-config.ts +0 -90
  453. package/src/wirings/role/define-system-role.ts +0 -33
  454. package/src/wirings/role/index.ts +0 -13
  455. package/src/wirings/role/role.test.ts +0 -104
  456. package/src/wirings/role/role.types.ts +0 -47
  457. package/src/wirings/role/validate-role-definitions.ts +0 -93
  458. package/src/wirings/rpc/index.ts +0 -8
  459. package/src/wirings/rpc/rpc-runner.test.ts +0 -1130
  460. package/src/wirings/rpc/rpc-runner.ts +0 -569
  461. package/src/wirings/rpc/rpc-types.ts +0 -87
  462. package/src/wirings/scheduler/index.ts +0 -11
  463. package/src/wirings/scheduler/log-schedulers.ts +0 -16
  464. package/src/wirings/scheduler/scheduler-runner.test.ts +0 -835
  465. package/src/wirings/scheduler/scheduler-runner.ts +0 -138
  466. package/src/wirings/scheduler/scheduler.types.ts +0 -42
  467. package/src/wirings/scope/define-scope.ts +0 -33
  468. package/src/wirings/scope/index.ts +0 -15
  469. package/src/wirings/scope/scope.test.ts +0 -159
  470. package/src/wirings/scope/scope.types.ts +0 -42
  471. package/src/wirings/scope/validate-scope-definitions.ts +0 -107
  472. package/src/wirings/secret/index.ts +0 -9
  473. package/src/wirings/secret/secret.types.ts +0 -70
  474. package/src/wirings/secret/validate-secret-definitions.test.ts +0 -232
  475. package/src/wirings/secret/validate-secret-definitions.ts +0 -88
  476. package/src/wirings/trigger/index.ts +0 -9
  477. package/src/wirings/trigger/pikku-trigger-service.ts +0 -107
  478. package/src/wirings/trigger/trigger-runner.test.ts +0 -78
  479. package/src/wirings/trigger/trigger-runner.ts +0 -113
  480. package/src/wirings/trigger/trigger.types.ts +0 -100
  481. package/src/wirings/variable/index.ts +0 -8
  482. package/src/wirings/variable/validate-variable-definitions.test.ts +0 -115
  483. package/src/wirings/variable/validate-variable-definitions.ts +0 -71
  484. package/src/wirings/variable/variable.types.ts +0 -40
  485. package/src/wirings/virtual-user/index.ts +0 -107
  486. package/src/wirings/virtual-user/prepare-virtual-user-run.test.ts +0 -115
  487. package/src/wirings/virtual-user/prepare-virtual-user-run.ts +0 -95
  488. package/src/wirings/virtual-user/run-virtual-user.test.ts +0 -774
  489. package/src/wirings/virtual-user/run-virtual-user.ts +0 -684
  490. package/src/wirings/virtual-user/virtual-user-agents.test.ts +0 -72
  491. package/src/wirings/virtual-user/virtual-user-agents.ts +0 -62
  492. package/src/wirings/virtual-user/virtual-user-catalogue.test.ts +0 -215
  493. package/src/wirings/virtual-user/virtual-user-catalogue.ts +0 -184
  494. package/src/wirings/virtual-user/virtual-user-derive.test.ts +0 -426
  495. package/src/wirings/virtual-user/virtual-user-derive.ts +0 -161
  496. package/src/wirings/virtual-user/virtual-user-dispositions.test.ts +0 -68
  497. package/src/wirings/virtual-user/virtual-user-dispositions.ts +0 -210
  498. package/src/wirings/virtual-user/virtual-user-intents.test.ts +0 -218
  499. package/src/wirings/virtual-user/virtual-user-intents.ts +0 -185
  500. package/src/wirings/virtual-user/virtual-user-rng.test.ts +0 -72
  501. package/src/wirings/virtual-user/virtual-user-rng.ts +0 -50
  502. package/src/wirings/virtual-user/virtual-user-run-store.ts +0 -131
  503. package/src/wirings/virtual-user/virtual-user-scaffold.test.ts +0 -854
  504. package/src/wirings/virtual-user/virtual-user-scaffold.ts +0 -664
  505. package/src/wirings/virtual-user/virtual-user-schedule-store.ts +0 -93
  506. package/src/wirings/virtual-user/virtual-user-schedule.test.ts +0 -280
  507. package/src/wirings/virtual-user/virtual-user-schedule.ts +0 -156
  508. package/src/wirings/virtual-user/virtual-user-target.ts +0 -47
  509. package/src/wirings/virtual-user/virtual-user.types.ts +0 -215
  510. package/src/wirings/workflow/dsl/workflow-dsl.types.ts +0 -709
  511. package/src/wirings/workflow/dsl/workflow-runner.ts +0 -25
  512. package/src/wirings/workflow/feature.test.ts +0 -131
  513. package/src/wirings/workflow/feature.ts +0 -59
  514. package/src/wirings/workflow/graph/graph-foreach-queued.test.ts +0 -569
  515. package/src/wirings/workflow/graph/graph-foreach.test.ts +0 -626
  516. package/src/wirings/workflow/graph/graph-node.ts +0 -115
  517. package/src/wirings/workflow/graph/graph-runner.test.ts +0 -1049
  518. package/src/wirings/workflow/graph/graph-runner.ts +0 -1376
  519. package/src/wirings/workflow/graph/graph-validation.test.ts +0 -27
  520. package/src/wirings/workflow/graph/graph-validation.ts +0 -41
  521. package/src/wirings/workflow/graph/template.test.ts +0 -49
  522. package/src/wirings/workflow/graph/template.ts +0 -42
  523. package/src/wirings/workflow/graph/wire-workflow-graph.ts +0 -39
  524. package/src/wirings/workflow/graph/workflow-graph.types.ts +0 -75
  525. package/src/wirings/workflow/index.ts +0 -107
  526. package/src/wirings/workflow/pikku-scenario-service.ts +0 -1013
  527. package/src/wirings/workflow/pikku-workflow-service.test.ts +0 -963
  528. package/src/wirings/workflow/pikku-workflow-service.ts +0 -1993
  529. package/src/wirings/workflow/run-timeline.test.ts +0 -199
  530. package/src/wirings/workflow/run-timeline.ts +0 -185
  531. package/src/wirings/workflow/scenario-cookie-jar.test.ts +0 -107
  532. package/src/wirings/workflow/scenario-cookie-jar.ts +0 -57
  533. package/src/wirings/workflow/scenario-expectations.test.ts +0 -238
  534. package/src/wirings/workflow/scenario-hooks.test.ts +0 -259
  535. package/src/wirings/workflow/scenario-poll.test.ts +0 -64
  536. package/src/wirings/workflow/scenario-poll.ts +0 -27
  537. package/src/wirings/workflow/scenario-prose.test.ts +0 -275
  538. package/src/wirings/workflow/scenario-prose.ts +0 -86
  539. package/src/wirings/workflow/scenario-run.types.ts +0 -193
  540. package/src/wirings/workflow/scenario-service.test.ts +0 -147
  541. package/src/wirings/workflow/scenario-step-guards.ts +0 -23
  542. package/src/wirings/workflow/scenario-step.test.ts +0 -800
  543. package/src/wirings/workflow/scenario-step.types.ts +0 -262
  544. package/src/wirings/workflow/scenario-surface.test.ts +0 -146
  545. package/src/wirings/workflow/scenario-surface.ts +0 -71
  546. package/src/wirings/workflow/scenario.types.ts +0 -63
  547. package/src/wirings/workflow/workflow-approval-audit.ts +0 -47
  548. package/src/wirings/workflow/workflow-approval-policy.test.ts +0 -594
  549. package/src/wirings/workflow/workflow-approval-policy.ts +0 -68
  550. package/src/wirings/workflow/workflow-approval.ts +0 -290
  551. package/src/wirings/workflow/workflow-child-run-session.test.ts +0 -168
  552. package/src/wirings/workflow/workflow-constants.ts +0 -66
  553. package/src/wirings/workflow/workflow-dispatch-durability.test.ts +0 -116
  554. package/src/wirings/workflow/workflow-dispatch-payload.test.ts +0 -55
  555. package/src/wirings/workflow/workflow-dispatch-relay.test.ts +0 -128
  556. package/src/wirings/workflow/workflow-errors.ts +0 -132
  557. package/src/wirings/workflow/workflow-inline-authority.test.ts +0 -175
  558. package/src/wirings/workflow/workflow-invocation-id.test.ts +0 -51
  559. package/src/wirings/workflow/workflow-invocation-id.ts +0 -28
  560. package/src/wirings/workflow/workflow-meta-resolver.ts +0 -45
  561. package/src/wirings/workflow/workflow-mirror.test.ts +0 -171
  562. package/src/wirings/workflow/workflow-missing-meta.test.ts +0 -92
  563. package/src/wirings/workflow/workflow-on-error.test.ts +0 -145
  564. package/src/wirings/workflow/workflow-queue-routing.ts +0 -129
  565. package/src/wirings/workflow/workflow-queue-wiring.ts +0 -149
  566. package/src/wirings/workflow/workflow-queue-workers.test.ts +0 -131
  567. package/src/wirings/workflow/workflow-queue-workers.ts +0 -66
  568. package/src/wirings/workflow/workflow-recovery.ts +0 -192
  569. package/src/wirings/workflow/workflow-replay-snapshot.test.ts +0 -140
  570. package/src/wirings/workflow/workflow-retry-policy.test.ts +0 -113
  571. package/src/wirings/workflow/workflow-run-authority.test.ts +0 -212
  572. package/src/wirings/workflow/workflow-run-context.test.ts +0 -172
  573. package/src/wirings/workflow/workflow-run-engine.types.ts +0 -92
  574. package/src/wirings/workflow/workflow-run-ownership.ts +0 -37
  575. package/src/wirings/workflow/workflow-run-polling.test.ts +0 -127
  576. package/src/wirings/workflow/workflow-stalled-recovery.test.ts +0 -152
  577. package/src/wirings/workflow/workflow-status-stream.test.ts +0 -354
  578. package/src/wirings/workflow/workflow-status-stream.ts +0 -144
  579. package/src/wirings/workflow/workflow-step-claim.ts +0 -46
  580. package/src/wirings/workflow/workflow-step-ordinal.test.ts +0 -94
  581. package/src/wirings/workflow/workflow-step-session.test.ts +0 -87
  582. package/src/wirings/workflow/workflow-suspend.ts +0 -61
  583. package/src/wirings/workflow/workflow-terminal-run-guard.test.ts +0 -105
  584. package/src/wirings/workflow/workflow.types.ts +0 -268
  585. package/src/wirings-stay-decoupled.test.ts +0 -130
  586. package/tsconfig.json +0 -14
  587. package/tsconfig.tsbuildinfo +0 -1
  588. package/tsconfig.type-tests.json +0 -15
@@ -1,152 +0,0 @@
1
- import { describe, test } from 'node:test'
2
- import assert from 'node:assert/strict'
3
-
4
- import { InMemoryWorkflowService } from '../../services/in-memory-workflow-service.js'
5
- import { pikkuState } from '../../pikku-state.js'
6
-
7
- const silentLogger = { error() {}, info() {}, warn() {}, debug() {} }
8
-
9
- /**
10
- * `recoverStalledRuns` re-drives a run by putting it back on the orchestrator
11
- * queue, so the queue is the observation point.
12
- */
13
- function trackResumes(): { runIds: string[] } {
14
- const seen: string[] = []
15
- pikkuState(null, 'package', 'singletonServices', {
16
- queueService: {
17
- add: async (_queue: string, data: { runId: string }) => {
18
- seen.push(data.runId)
19
- },
20
- },
21
- logger: silentLogger,
22
- } as any)
23
- return { runIds: seen }
24
- }
25
-
26
- /** Backdates every persisted timestamp so the run reads as idle. */
27
- async function backdate(
28
- ws: InMemoryWorkflowService,
29
- runId: string,
30
- ms: number
31
- ): Promise<void> {
32
- const past = new Date(Date.now() - ms)
33
- const run = await ws.getRun(runId)
34
- ;(run as any).updatedAt = past
35
- for (const step of await ws.getRunHistory(runId)) {
36
- ;(step as any).updatedAt = past
37
- }
38
- }
39
-
40
- describe('stalled run recovery', () => {
41
- test('resumes a running run left with a pending step and nothing in flight', async () => {
42
- const resumes = trackResumes()
43
- const ws = new InMemoryWorkflowService()
44
- const runId = await ws.createRun('flow', {}, false, 'hash', {
45
- type: 'test',
46
- })
47
- // A sleep whose timer was never armed: the step row exists, nothing will
48
- // ever complete it.
49
- await ws.insertStepState(runId, 'Wait 15s', null, { duration: 15000 })
50
- await backdate(ws, runId, 10 * 60_000)
51
-
52
- const { resumed } = await ws.recoverStalledRuns()
53
-
54
- assert.deepEqual(resumed, [runId], 'the orphaned run is resumed')
55
- assert.deepEqual(resumes.runIds, [runId], 'it is put back on the queue')
56
- })
57
-
58
- test('leaves a run alone while a step is still scheduled', async () => {
59
- trackResumes()
60
- const ws = new InMemoryWorkflowService()
61
- const runId = await ws.createRun('flow', {}, false, 'hash', {
62
- type: 'test',
63
- })
64
- const step = await ws.insertStepState(runId, 'Wait 1h', null, {
65
- duration: 3_600_000,
66
- })
67
- await ws.setStepScheduled(step.stepId)
68
- await backdate(ws, runId, 10 * 60_000)
69
-
70
- const { resumed } = await ws.recoverStalledRuns()
71
-
72
- assert.deepEqual(
73
- resumed,
74
- [],
75
- 'a legitimately sleeping run is not a stalled run'
76
- )
77
- })
78
-
79
- test('leaves a run alone until it has actually gone idle', async () => {
80
- trackResumes()
81
- const ws = new InMemoryWorkflowService()
82
- const runId = await ws.createRun('flow', {}, false, 'hash', {
83
- type: 'test',
84
- })
85
- await ws.insertStepState(runId, 'Wait 15s', null, { duration: 15000 })
86
-
87
- const { resumed } = await ws.recoverStalledRuns()
88
-
89
- assert.deepEqual(resumed, [], 'a run that just moved is not swept')
90
- })
91
-
92
- test('backs off rather than re-resuming the same run every tick', async () => {
93
- const resumes = trackResumes()
94
- const ws = new InMemoryWorkflowService()
95
- const runId = await ws.createRun('flow', {}, false, 'hash', {
96
- type: 'test',
97
- })
98
- await ws.insertStepState(runId, 'Wait 15s', null, { duration: 15000 })
99
- await backdate(ws, runId, 10 * 60_000)
100
-
101
- const first = await ws.recoverStalledRuns()
102
- // Still stalled: a resume does not clear whatever wedged the run, so an
103
- // unconditional sweep would re-queue it on this tick and on every tick
104
- // after it.
105
- const second = await ws.recoverStalledRuns()
106
-
107
- assert.deepEqual(first.resumed, [runId], 'the first sweep resumes it')
108
- assert.deepEqual(
109
- second.resumed,
110
- [],
111
- 'the next sweep is held off by the backoff'
112
- )
113
- assert.deepEqual(resumes.runIds, [runId], 'only one queue message')
114
- })
115
-
116
- test('does not re-drive a run the relay has just re-dispatched', async () => {
117
- const resumes = trackResumes()
118
- const ws = new InMemoryWorkflowService()
119
- const runId = await ws.createRun('flow', {}, false, 'hash', {
120
- type: 'test',
121
- })
122
- // Old enough to read as both an undispatched step and a stalled run.
123
- await ws.insertStepState(runId, 'Wait 15s', null, { duration: 15000 })
124
- await backdate(ws, runId, 10 * 60_000)
125
-
126
- const relayed = await ws.relayUndispatchedSteps()
127
- const swept = await ws.recoverStalledRuns()
128
-
129
- assert.deepEqual(relayed.redispatched, [runId], 'the relay re-drives it')
130
- assert.deepEqual(
131
- swept.resumed,
132
- [],
133
- 'the sweep adds nothing the relay has not already queued'
134
- )
135
- assert.deepEqual(resumes.runIds, [runId], 'only one queue message')
136
- })
137
-
138
- test('leaves a finished run alone', async () => {
139
- trackResumes()
140
- const ws = new InMemoryWorkflowService()
141
- const runId = await ws.createRun('flow', {}, false, 'hash', {
142
- type: 'test',
143
- })
144
- await ws.insertStepState(runId, 'Wait 15s', null, { duration: 15000 })
145
- await ws.updateRunStatus(runId, 'completed')
146
- await backdate(ws, runId, 10 * 60_000)
147
-
148
- const { resumed } = await ws.recoverStalledRuns()
149
-
150
- assert.deepEqual(resumed, [], 'only running runs are swept')
151
- })
152
- })
@@ -1,354 +0,0 @@
1
- import { test, describe } from 'node:test'
2
- import assert from 'node:assert/strict'
3
- import { streamWorkflowRunStatus } from './workflow-status-stream.js'
4
- import type { WorkflowRunService } from './workflow.types.js'
5
-
6
- const run = (over: Record<string, unknown> = {}) =>
7
- ({
8
- id: 'run-1',
9
- workflow: 'checkout',
10
- status: 'running',
11
- input: {},
12
- wire: {},
13
- createdAt: new Date(),
14
- updatedAt: new Date(),
15
- ...over,
16
- }) as any
17
-
18
- const step = (stepName: string, status: string, over: any = {}) =>
19
- ({ stepId: stepName, stepName, status, attemptCount: 1, ...over }) as any
20
-
21
- /**
22
- * Each poll is driven by a scripted sequence rather than a clock, so a test
23
- * asserts what the stream sends without waiting for one.
24
- */
25
- const harness = (
26
- polls: Array<{ run: any; steps: any[] }>,
27
- { detailed = false, session = undefined as any } = {}
28
- ) => {
29
- const sent: any[] = []
30
- let closed = false
31
- let index = 0
32
- const workflowRunService = {
33
- getRun: async () => {
34
- const frame = polls[Math.min(index, polls.length - 1)]
35
- return frame!.run
36
- },
37
- getRunSteps: async () => {
38
- const frame = polls[Math.min(index, polls.length - 1)]
39
- index += 1
40
- return frame!.steps
41
- },
42
- } as unknown as WorkflowRunService
43
-
44
- return {
45
- sent,
46
- closed: () => closed,
47
- stream: () =>
48
- streamWorkflowRunStatus({
49
- workflowRunService,
50
- runId: 'run-1',
51
- channel: {
52
- send: async (data: any) => {
53
- sent.push(data)
54
- },
55
- close: async () => {
56
- closed = true
57
- },
58
- },
59
- session,
60
- detailed,
61
- pollIntervalMs: 1,
62
- }),
63
- }
64
- }
65
-
66
- describe('streamWorkflowRunStatus', () => {
67
- test('a run that is already finished never starts a timer', async () => {
68
- const h = harness([
69
- { run: run({ status: 'completed' }), steps: [step('a', 'succeeded')] },
70
- ])
71
- await h.stream()
72
- assert.deepEqual(
73
- h.sent.map((frame) => frame.type),
74
- ['update', 'done']
75
- )
76
- assert.equal(h.closed(), true)
77
- })
78
-
79
- test('a run nobody can find closes the stream rather than hanging', async () => {
80
- const h = harness([{ run: null, steps: [] }])
81
- await h.stream()
82
- assert.equal(h.sent.length, 0)
83
- assert.equal(h.closed(), true)
84
- })
85
-
86
- // Checked on every poll, not just the first: a stream that outlives a session
87
- // should stop rather than keep reporting.
88
- test('a run belonging to someone else is refused', async () => {
89
- const h = harness(
90
- [{ run: run({ wire: { pikkuUserId: 'someone-else' } }), steps: [] }],
91
- { session: { userId: 'me' } }
92
- )
93
- await assert.rejects(
94
- h.stream(),
95
- /Not authorized to access this workflow run/
96
- )
97
- })
98
-
99
- // A deterministic run knows its whole shape up front, so the client can draw
100
- // every step — including the ones not started — before anything runs.
101
- test('a deterministic run sends its planned shape first', async () => {
102
- const h = harness([
103
- {
104
- run: run({
105
- status: 'completed',
106
- deterministic: true,
107
- plannedSteps: [{ stepName: 'a' }, { stepName: 'b' }],
108
- }),
109
- steps: [step('a', 'succeeded')],
110
- },
111
- ])
112
- await h.stream()
113
- const init = h.sent[0]
114
- assert.equal(init.type, 'init')
115
- assert.equal(init.deterministic, true)
116
- assert.deepEqual(init.steps, [
117
- { stepName: 'a', status: 'succeeded' },
118
- // Planned but not started, which is the whole reason to send this frame.
119
- { stepName: 'b', status: 'pending' },
120
- ])
121
- })
122
-
123
- test('a dynamic run has no shape to announce, so it announces none', async () => {
124
- const h = harness([
125
- { run: run({ status: 'completed' }), steps: [step('a', 'succeeded')] },
126
- ])
127
- await h.stream()
128
- assert.equal(
129
- h.sent.some((frame) => frame.type === 'init'),
130
- false
131
- )
132
- })
133
-
134
- // A run sitting on a slow step should cost one message, not one per poll.
135
- test('nothing is sent while nothing has changed', async () => {
136
- const h = harness([
137
- { run: run(), steps: [step('a', 'running')] },
138
- { run: run(), steps: [step('a', 'running')] },
139
- { run: run(), steps: [step('a', 'running')] },
140
- {
141
- run: run({ status: 'completed' }),
142
- steps: [step('a', 'succeeded')],
143
- },
144
- ])
145
- await h.stream()
146
- assert.deepEqual(
147
- h.sent.map((frame) => frame.type),
148
- ['update', 'update', 'done']
149
- )
150
- })
151
-
152
- test('every terminal status ends the stream', async () => {
153
- for (const status of ['completed', 'failed', 'cancelled']) {
154
- const h = harness([{ run: run({ status }), steps: [] }])
155
- await h.stream()
156
- assert.equal(h.sent.at(-1)!.type, 'done', status)
157
- assert.equal(h.closed(), true, status)
158
- }
159
- })
160
-
161
- // The whole difference between the two scaffolded routes. A workflow's output
162
- // and its error messages are internal detail, and a step that spawned a child
163
- // run says so only to tooling that can follow it.
164
- test('the user-facing stream reports progress and nothing else', async () => {
165
- const h = harness([
166
- {
167
- run: run({
168
- status: 'failed',
169
- output: { card: '4242' },
170
- error: { message: 'declined at acquirer', name: 'Error' },
171
- }),
172
- steps: [step('a', 'failed', { childRunId: 'child-1' })],
173
- },
174
- ])
175
- await h.stream()
176
- const update = h.sent[0]
177
- assert.equal(update.status, 'failed')
178
- assert.equal('output' in update, false)
179
- assert.equal('error' in update, false)
180
- assert.deepEqual(update.steps, [{ stepName: 'a', status: 'failed' }])
181
- })
182
-
183
- test('the detailed stream carries what the run produced', async () => {
184
- const h = harness(
185
- [
186
- {
187
- run: run({
188
- status: 'failed',
189
- output: { card: '4242' },
190
- error: { message: 'declined at acquirer', name: 'Error' },
191
- }),
192
- steps: [step('a', 'failed', { childRunId: 'child-1' })],
193
- },
194
- ],
195
- { detailed: true }
196
- )
197
- await h.stream()
198
- const update = h.sent[0]
199
- assert.deepEqual(update.output, { card: '4242' })
200
- assert.equal(update.error.message, 'declined at acquirer')
201
- assert.deepEqual(update.steps, [
202
- { stepName: 'a', status: 'failed', childRunId: 'child-1' },
203
- ])
204
- })
205
-
206
- // The detailed stream compares output too, so a run whose steps are unchanged
207
- // but whose output has moved on still reports it.
208
- test('a change only the detailed stream can see still reaches it', async () => {
209
- const frames = [
210
- { run: run({ output: { progress: 1 } }), steps: [step('a', 'running')] },
211
- { run: run({ output: { progress: 2 } }), steps: [step('a', 'running')] },
212
- {
213
- run: run({ status: 'completed', output: { progress: 2 } }),
214
- steps: [step('a', 'succeeded')],
215
- },
216
- ]
217
- const quiet = harness(frames)
218
- await quiet.stream()
219
- assert.equal(
220
- quiet.sent.filter((frame) => frame.type === 'update').length,
221
- 2
222
- )
223
-
224
- const loud = harness(frames, { detailed: true })
225
- await loud.stream()
226
- assert.equal(loud.sent.filter((frame) => frame.type === 'update').length, 3)
227
- })
228
-
229
- // Without this the throw is an unhandled rejection from a timer callback,
230
- // which takes the process with it rather than failing the request.
231
- test('a poll that throws after the first stops the stream, loudly', async () => {
232
- let calls = 0
233
- await assert.rejects(
234
- streamWorkflowRunStatus({
235
- workflowRunService: {
236
- getRun: async () => {
237
- calls += 1
238
- if (calls > 1) {
239
- throw new Error('the database went away')
240
- }
241
- return run()
242
- },
243
- getRunSteps: async () => [],
244
- } as unknown as WorkflowRunService,
245
- runId: 'run-1',
246
- channel: { send: async () => {}, close: async () => {} },
247
- session: undefined,
248
- pollIntervalMs: 1,
249
- }),
250
- /the database went away/
251
- )
252
- })
253
- })
254
-
255
- /**
256
- * A stream that throws still has a channel open on the other end. The owner
257
- * check runs on every poll precisely so a session that loses access stops the
258
- * stream — which is only true if stopping also closes it.
259
- */
260
- describe('streamWorkflowRunStatus closes the channel when a poll throws', () => {
261
- const failingStream = (failOn: number) => {
262
- let closed = false
263
- let polls = 0
264
- const workflowRunService = {
265
- getRun: async () => {
266
- polls += 1
267
- if (polls >= failOn) {
268
- throw new Error('run store unavailable')
269
- }
270
- return run()
271
- },
272
- getRunSteps: async () => [step('charge', 'running')],
273
- } as unknown as WorkflowRunService
274
-
275
- return {
276
- closed: () => closed,
277
- stream: () =>
278
- streamWorkflowRunStatus({
279
- workflowRunService,
280
- runId: 'run-1',
281
- channel: {
282
- send: async () => {},
283
- close: async () => {
284
- closed = true
285
- },
286
- },
287
- session: undefined as any,
288
- pollIntervalMs: 1,
289
- }),
290
- }
291
- }
292
-
293
- test('the first poll throwing closes the channel and rethrows', async () => {
294
- const h = failingStream(1)
295
- await assert.rejects(h.stream(), /run store unavailable/)
296
- assert.equal(h.closed(), true, 'a throw must not leave the channel open')
297
- })
298
-
299
- test('a later poll throwing closes the channel and rethrows', async () => {
300
- const h = failingStream(3)
301
- await assert.rejects(h.stream(), /run store unavailable/)
302
- assert.equal(h.closed(), true, 'a throw must not leave the channel open')
303
- })
304
- })
305
-
306
- /**
307
- * The poll used to be on a fixed interval, which fires whether or not the
308
- * previous one has come back. Two in flight at once both see `initSent` unset
309
- * and send the init frame twice.
310
- */
311
- describe('streamWorkflowRunStatus never runs two polls at once', () => {
312
- test('a poll slower than the interval does not overlap the next', async () => {
313
- const sent: any[] = []
314
- let inFlight = 0
315
- let overlapped = false
316
- let polls = 0
317
-
318
- const workflowRunService = {
319
- getRun: async () => {
320
- inFlight += 1
321
- if (inFlight > 1) overlapped = true
322
- await new Promise((r) => setTimeout(r, 15))
323
- polls += 1
324
- inFlight -= 1
325
- return run({
326
- status: polls >= 3 ? 'completed' : 'running',
327
- deterministic: true,
328
- plannedSteps: [{ stepName: 'charge' }],
329
- })
330
- },
331
- getRunSteps: async () => [step('charge', 'running')],
332
- } as unknown as WorkflowRunService
333
-
334
- await streamWorkflowRunStatus({
335
- workflowRunService,
336
- runId: 'run-1',
337
- channel: {
338
- send: async (d: any) => {
339
- sent.push(d)
340
- },
341
- close: async () => {},
342
- },
343
- session: undefined as any,
344
- pollIntervalMs: 1,
345
- })
346
-
347
- assert.equal(overlapped, false, 'two polls must never be in flight together')
348
- assert.equal(
349
- sent.filter((f) => f.type === 'init').length,
350
- 1,
351
- 'the init frame is sent exactly once'
352
- )
353
- })
354
- })
@@ -1,144 +0,0 @@
1
- import type { CoreUserSession } from '../../types/core.types.js'
2
- import type { PikkuChannel } from '../channel/channel.types.js'
3
- import { assertWorkflowRunOwner } from './workflow-run-ownership.js'
4
- import type { WorkflowRunService, WorkflowStatus } from './workflow.types.js'
5
-
6
- /**
7
- * The status stream behind the scaffolded workflow SSE routes.
8
- *
9
- * Two routes share it, and they differ by one thing: whether the caller is
10
- * trusted with what the run produced. A user-facing frontend gets step names
11
- * and statuses; an admin console also gets the output, the error and the child
12
- * run ids. That is a parameter, not a second copy of the loop.
13
- */
14
-
15
- const TERMINAL: ReadonlySet<string> = new Set<WorkflowStatus>([
16
- 'completed',
17
- 'failed',
18
- 'cancelled',
19
- ])
20
-
21
- const DEFAULT_POLL_INTERVAL_MS = 500
22
-
23
- export interface WorkflowStatusStreamParams {
24
- workflowRunService: WorkflowRunService
25
- runId: string
26
- channel: Pick<PikkuChannel<unknown, any>, 'send' | 'close'>
27
- session: CoreUserSession | undefined
28
- /**
29
- * Whether to include what the run produced. Off for the user-facing route:
30
- * a workflow's output and its error messages are internal detail, and a step
31
- * that spawned a child run says so only to tooling that can follow it.
32
- */
33
- detailed?: boolean
34
- pollIntervalMs?: number
35
- }
36
-
37
- /**
38
- * Streams one run's progress until it reaches a terminal state.
39
- *
40
- * Polled rather than subscribed because a run's steps are written by whichever
41
- * worker picked them up, in whichever process — there is no in-memory event to
42
- * listen for that every deployment shape would deliver.
43
- *
44
- * Each poll sends only when something changed, compared by a hash of exactly
45
- * what this stream reports. A run that sits on a slow step for a minute costs
46
- * one message, not a hundred and twenty.
47
- */
48
- export const streamWorkflowRunStatus = async ({
49
- workflowRunService,
50
- runId,
51
- channel,
52
- session,
53
- detailed = false,
54
- pollIntervalMs = DEFAULT_POLL_INTERVAL_MS,
55
- }: WorkflowStatusStreamParams): Promise<void> => {
56
- let lastHash = ''
57
- let initSent = false
58
-
59
- const poll = async (): Promise<boolean> => {
60
- const run = await workflowRunService.getRun(runId)
61
- if (!run) {
62
- await channel.close()
63
- return false
64
- }
65
- // Checked on every poll, not just the first: ownership is read from the run
66
- // itself, and a stream that outlives a session should stop rather than keep
67
- // reporting.
68
- assertWorkflowRunOwner(run.wire, session)
69
-
70
- const steps = await workflowRunService.getRunSteps(runId)
71
-
72
- // A deterministic run knows its whole shape up front, so the client can
73
- // draw every step — including the ones not started — before anything runs.
74
- // A dynamic run has nothing to send here, and gets no init frame.
75
- if (!initSent && run.deterministic) {
76
- const statusByStep = new Map(
77
- steps.map((step) => [step.stepName, step.status])
78
- )
79
- await channel.send({
80
- type: 'init',
81
- deterministic: true,
82
- steps: (run.plannedSteps ?? []).map((step) => ({
83
- stepName: step.stepName,
84
- status: statusByStep.get(step.stepName) ?? 'pending',
85
- })),
86
- })
87
- initSent = true
88
- }
89
-
90
- const hash = JSON.stringify({
91
- s: run.status,
92
- ...(detailed ? { o: run.output } : {}),
93
- steps: steps.map((step) => [step.stepName, step.status]),
94
- })
95
-
96
- if (hash !== lastHash) {
97
- lastHash = hash
98
- await channel.send({
99
- type: 'update',
100
- status: run.status,
101
- ...(detailed ? { output: run.output, error: run.error } : {}),
102
- steps: steps.map((step) => ({
103
- stepName: step.stepName,
104
- status: step.status,
105
- ...(detailed && step.childRunId
106
- ? { childRunId: step.childRunId }
107
- : {}),
108
- })),
109
- })
110
- }
111
-
112
- if (TERMINAL.has(run.status)) {
113
- await channel.send({ type: 'done' })
114
- await channel.close()
115
- return false
116
- }
117
- return true
118
- }
119
-
120
- // Every exit from here closes the channel, including the ones a throw takes:
121
- // `assertWorkflowRunOwner` rejecting a session that lost access is exactly
122
- // the case where the stream should end rather than be left hanging open.
123
- try {
124
- // A run that is already finished is answered without ever starting a timer.
125
- if (!(await poll())) {
126
- return
127
- }
128
-
129
- // The next poll is scheduled when the previous one resolves rather than on
130
- // a fixed interval. A timer that fires regardless would let two polls
131
- // overlap on a slow store — both seeing `initSent` unset and sending the
132
- // init frame twice, and racing `lastHash` into out-of-order updates.
133
- while (
134
- await new Promise<boolean>((resolve, reject) => {
135
- setTimeout(() => void poll().then(resolve, reject), pollIntervalMs)
136
- })
137
- ) {
138
- // The condition is the whole loop: poll until it says to stop.
139
- }
140
- } catch (error) {
141
- await channel.close()
142
- throw error
143
- }
144
- }
@@ -1,46 +0,0 @@
1
- import { WorkflowStepFunctionMismatchError } from './workflow-errors.js'
2
- import type { StepState } from './workflow.types.js'
3
-
4
- /** What claiming a step needs from the workflow service. */
5
- export type StepClaimStore = {
6
- getStepState(runId: string, stepName: string): Promise<StepState>
7
- setStepRunning(stepId: string): Promise<void>
8
- createRetryAttempt(
9
- failedStepId: string,
10
- status: 'pending' | 'running'
11
- ): Promise<StepState>
12
- }
13
-
14
- /**
15
- * Decide whether this dispatch owns the step, by reading its state and then
16
- * writing it — which only excludes a concurrent dispatch when the caller holds
17
- * a lock that genuinely excludes one.
18
- *
19
- * A store that can express the whole decision as a single conditional write
20
- * should do that instead of calling this.
21
- */
22
- export const claimStepByReadThenWrite = async (
23
- store: StepClaimStore,
24
- runId: string,
25
- stepName: string,
26
- rpcName: string
27
- ): Promise<StepState | null> => {
28
- const stepState = await store.getStepState(runId, stepName)
29
- // knowledge: decisions/security/a-step-runs-the-function-the-workflow-dispatched-it-with.md
30
- if (
31
- stepState.rpcName !== undefined &&
32
- stepState.rpcName !== (rpcName ?? null)
33
- ) {
34
- throw new WorkflowStepFunctionMismatchError(runId, stepName)
35
- }
36
- if (stepState.status === 'succeeded' || stepState.status === 'running') {
37
- return null
38
- }
39
- if (stepState.status === 'failed') {
40
- return store.createRetryAttempt(stepState.stepId, 'running')
41
- }
42
- if (stepState.status === 'pending' || stepState.status === 'scheduled') {
43
- await store.setStepRunning(stepState.stepId)
44
- }
45
- return stepState
46
- }