@pikku/core 0.12.72 → 0.12.77

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 (848) hide show
  1. package/CHANGELOG.md +1171 -0
  2. package/dist/column-form.d.ts +32 -0
  3. package/dist/column-form.js +42 -0
  4. package/dist/crypto-utils.d.ts +43 -7
  5. package/dist/crypto-utils.js +163 -42
  6. package/dist/data-classification.d.ts +44 -0
  7. package/dist/dev/hot-reload.js +11 -30
  8. package/dist/dev/module-runner.d.ts +3 -7
  9. package/dist/dev/module-runner.js +4 -10
  10. package/dist/dev/reload-meta.d.ts +8 -20
  11. package/dist/dev/reload-meta.js +9 -29
  12. package/dist/errors/error-handler.d.ts +5 -30
  13. package/dist/errors/error-handler.js +16 -32
  14. package/dist/errors/errors.d.ts +32 -151
  15. package/dist/errors/errors.js +55 -157
  16. package/dist/function/abort-scope.d.ts +47 -0
  17. package/dist/function/abort-scope.js +63 -0
  18. package/dist/function/function-runner.js +37 -32
  19. package/dist/function/functions.types.d.ts +57 -136
  20. package/dist/function/functions.types.js +0 -58
  21. package/dist/function/index.d.ts +1 -1
  22. package/dist/function/list.types.d.ts +12 -62
  23. package/dist/function/list.types.js +4 -25
  24. package/dist/handle-error.d.ts +0 -13
  25. package/dist/handle-error.js +0 -18
  26. package/dist/index.d.ts +11 -5
  27. package/dist/index.js +7 -2
  28. package/dist/middleware/auth-apikey.d.ts +3 -18
  29. package/dist/middleware/auth-apikey.js +0 -17
  30. package/dist/middleware/auth-bearer.d.ts +6 -41
  31. package/dist/middleware/auth-bearer.js +5 -41
  32. package/dist/middleware/auth-cookie.d.ts +5 -27
  33. package/dist/middleware/auth-cookie.js +2 -26
  34. package/dist/middleware/cors.d.ts +7 -34
  35. package/dist/middleware/cors.js +7 -34
  36. package/dist/middleware/remote-auth.d.ts +3 -1
  37. package/dist/middleware/remote-auth.js +4 -3
  38. package/dist/middleware/telemetry.d.ts +8 -33
  39. package/dist/middleware/telemetry.js +2 -31
  40. package/dist/middleware-runner.d.ts +4 -55
  41. package/dist/middleware-runner.js +5 -74
  42. package/dist/permissions.d.ts +3 -44
  43. package/dist/permissions.js +19 -71
  44. package/dist/pikku-request.d.ts +0 -6
  45. package/dist/pikku-request.js +0 -6
  46. package/dist/pikku-state.d.ts +0 -26
  47. package/dist/pikku-state.js +2 -30
  48. package/dist/remote.d.ts +3 -5
  49. package/dist/remote.js +9 -8
  50. package/dist/schema.d.ts +5 -39
  51. package/dist/schema.js +5 -39
  52. package/dist/scopes.d.ts +4 -23
  53. package/dist/scopes.js +7 -48
  54. package/dist/secret-value.d.ts +56 -0
  55. package/dist/secret-value.js +46 -0
  56. package/dist/services/ai-agent-runner-service.d.ts +20 -0
  57. package/dist/services/ai-embedding-service.d.ts +2 -25
  58. package/dist/services/audit-service.d.ts +74 -4
  59. package/dist/services/audit-service.js +8 -7
  60. package/dist/services/content-service.d.ts +1 -46
  61. package/dist/services/credential-service.d.ts +3 -40
  62. package/dist/services/credential-wire-service.d.ts +5 -0
  63. package/dist/services/credential-wire-service.js +9 -1
  64. package/dist/services/deployment-service.d.ts +3 -9
  65. package/dist/services/email-service.d.ts +2 -1
  66. package/dist/services/gateway-service.d.ts +0 -15
  67. package/dist/services/http-personas.d.ts +80 -0
  68. package/dist/services/http-personas.js +233 -0
  69. package/dist/services/in-memory-queue-service.d.ts +0 -14
  70. package/dist/services/in-memory-queue-service.js +1 -15
  71. package/dist/services/in-memory-trigger-service.d.ts +0 -18
  72. package/dist/services/in-memory-trigger-service.js +1 -18
  73. package/dist/services/in-memory-workflow-service.d.ts +0 -16
  74. package/dist/services/in-memory-workflow-service.js +4 -33
  75. package/dist/services/index.d.ts +8 -9
  76. package/dist/services/index.js +3 -6
  77. package/dist/services/istanbul-coverage-service.d.ts +1 -5
  78. package/dist/services/istanbul-coverage-service.js +2 -8
  79. package/dist/services/jwt-service.d.ts +1 -16
  80. package/dist/services/local-content-request-handler.d.ts +29 -0
  81. package/dist/services/local-content-request-handler.js +176 -0
  82. package/dist/services/local-content.d.ts +13 -2
  83. package/dist/services/local-content.js +40 -13
  84. package/dist/services/local-gateway-service.d.ts +0 -16
  85. package/dist/services/local-gateway-service.js +2 -17
  86. package/dist/services/local-secrets.d.ts +4 -7
  87. package/dist/services/local-secrets.js +7 -7
  88. package/dist/services/logger-console.d.ts +3 -7
  89. package/dist/services/logger-console.js +3 -7
  90. package/dist/services/logger.d.ts +22 -40
  91. package/dist/services/meta-service.d.ts +23 -26
  92. package/dist/services/meta-service.js +22 -36
  93. package/dist/services/personas-service.d.ts +134 -0
  94. package/dist/services/personas-service.js +40 -0
  95. package/dist/services/pikku-user-id.js +0 -4
  96. package/dist/services/queue-webhook-service.d.ts +2 -36
  97. package/dist/services/queue-webhook-service.js +10 -42
  98. package/dist/services/scheduler-service.d.ts +1 -50
  99. package/dist/services/scheduler-service.js +0 -10
  100. package/dist/services/schema-service.d.ts +1 -24
  101. package/dist/services/scope-service.d.ts +49 -34
  102. package/dist/services/scoped-secret-service.d.ts +4 -7
  103. package/dist/services/scoped-secret-service.js +0 -4
  104. package/dist/services/secret-host-binding.d.ts +8 -0
  105. package/dist/services/secret-host-binding.js +36 -0
  106. package/dist/services/secret-service.d.ts +12 -35
  107. package/dist/services/secretless.d.ts +6 -0
  108. package/dist/services/secretless.js +21 -0
  109. package/dist/services/stub-tracker.d.ts +7 -18
  110. package/dist/services/stub-tracker.js +8 -18
  111. package/dist/services/system-role-guard.d.ts +33 -0
  112. package/dist/services/system-role-guard.js +38 -0
  113. package/dist/services/trigger-service.d.ts +0 -12
  114. package/dist/services/typed-secret-service.d.ts +5 -11
  115. package/dist/services/typed-secret-service.js +1 -7
  116. package/dist/services/v8-coverage-service.d.ts +2 -3
  117. package/dist/services/v8-coverage-service.js +1 -2
  118. package/dist/services/variables-service.d.ts +1 -8
  119. package/dist/services/webhook-service.d.ts +21 -64
  120. package/dist/services/webhook-service.js +6 -20
  121. package/dist/services/workflow-service.d.ts +3 -15
  122. package/dist/testing/service-tests.js +6 -23
  123. package/dist/time-utils.d.ts +0 -16
  124. package/dist/time-utils.js +1 -19
  125. package/dist/types/core.types.d.ts +120 -219
  126. package/dist/types/core.types.js +0 -42
  127. package/dist/types/state.types.d.ts +4 -9
  128. package/dist/utils/hmac.d.ts +4 -10
  129. package/dist/utils/hmac.js +4 -10
  130. package/dist/utils/safe-fetch.d.ts +7 -35
  131. package/dist/utils/safe-fetch.js +13 -53
  132. package/dist/utils.d.ts +1 -6
  133. package/dist/utils.js +6 -15
  134. package/dist/wirings/actor-flow/actor-flow.types.d.ts +1 -34
  135. package/dist/wirings/actor-flow/index.d.ts +0 -9
  136. package/dist/wirings/actor-flow/run-conversation.d.ts +5 -5
  137. package/dist/wirings/actor-flow/run-conversation.js +14 -7
  138. package/dist/wirings/ai-agent/ai-agent-agui.d.ts +0 -5
  139. package/dist/wirings/ai-agent/ai-agent-agui.js +46 -12
  140. package/dist/wirings/ai-agent/ai-agent-helpers.d.ts +7 -0
  141. package/dist/wirings/ai-agent/ai-agent-helpers.js +7 -0
  142. package/dist/wirings/ai-agent/ai-agent-interrupt.d.ts +153 -0
  143. package/dist/wirings/ai-agent/ai-agent-interrupt.js +256 -0
  144. package/dist/wirings/ai-agent/ai-agent-memory.js +0 -2
  145. package/dist/wirings/ai-agent/ai-agent-model-config.d.ts +0 -9
  146. package/dist/wirings/ai-agent/ai-agent-model-config.js +1 -9
  147. package/dist/wirings/ai-agent/ai-agent-prepare.d.ts +10 -99
  148. package/dist/wirings/ai-agent/ai-agent-prepare.js +65 -132
  149. package/dist/wirings/ai-agent/ai-agent-registry.d.ts +2 -1
  150. package/dist/wirings/ai-agent/ai-agent-registry.js +5 -1
  151. package/dist/wirings/ai-agent/ai-agent-runner.js +63 -22
  152. package/dist/wirings/ai-agent/ai-agent-stream.d.ts +25 -2
  153. package/dist/wirings/ai-agent/ai-agent-stream.js +180 -64
  154. package/dist/wirings/ai-agent/ai-agent.types.d.ts +124 -4
  155. package/dist/wirings/ai-agent/index.d.ts +6 -4
  156. package/dist/wirings/ai-agent/index.js +5 -4
  157. package/dist/wirings/ai-agent/voice-input.d.ts +59 -1
  158. package/dist/wirings/ai-agent/voice-input.js +90 -12
  159. package/dist/wirings/ai-agent/voice-output.d.ts +69 -1
  160. package/dist/wirings/ai-agent/voice-output.js +162 -50
  161. package/dist/wirings/channel/channel-common.d.ts +7 -20
  162. package/dist/wirings/channel/channel-common.js +7 -21
  163. package/dist/wirings/channel/channel-handler.js +25 -6
  164. package/dist/wirings/channel/channel-host-rpc.d.ts +25 -0
  165. package/dist/wirings/channel/channel-host-rpc.js +38 -0
  166. package/dist/wirings/channel/channel-middleware-runner.d.ts +0 -12
  167. package/dist/wirings/channel/channel-middleware-runner.js +0 -12
  168. package/dist/wirings/channel/channel-rpc-registry.d.ts +31 -0
  169. package/dist/wirings/channel/channel-rpc-registry.js +89 -0
  170. package/dist/wirings/channel/channel-rpc-responder.d.ts +15 -0
  171. package/dist/wirings/channel/channel-rpc-responder.js +71 -0
  172. package/dist/wirings/channel/channel-rpc-service.d.ts +40 -0
  173. package/dist/wirings/channel/channel-rpc-service.js +106 -0
  174. package/dist/wirings/channel/channel-rpc-validators.d.ts +14 -0
  175. package/dist/wirings/channel/channel-rpc-validators.js +30 -0
  176. package/dist/wirings/channel/channel-rpc.d.ts +5 -0
  177. package/dist/wirings/channel/channel-rpc.js +5 -0
  178. package/dist/wirings/channel/channel-rpc.types.d.ts +90 -0
  179. package/dist/wirings/channel/channel-rpc.types.js +50 -0
  180. package/dist/wirings/channel/channel-runner.d.ts +0 -4
  181. package/dist/wirings/channel/channel-runner.js +0 -14
  182. package/dist/wirings/channel/channel-store.d.ts +0 -10
  183. package/dist/wirings/channel/channel.types.d.ts +12 -1
  184. package/dist/wirings/channel/define-channel-routes.d.ts +0 -20
  185. package/dist/wirings/channel/define-channel-routes.js +0 -20
  186. package/dist/wirings/channel/eventhub-service.d.ts +0 -18
  187. package/dist/wirings/channel/index.d.ts +4 -1
  188. package/dist/wirings/channel/index.js +2 -0
  189. package/dist/wirings/channel/local/local-channel-runner.js +3 -1
  190. package/dist/wirings/channel/local/local-eventhub-service.d.ts +0 -33
  191. package/dist/wirings/channel/local/local-eventhub-service.js +2 -36
  192. package/dist/wirings/channel/log-channels.d.ts +0 -4
  193. package/dist/wirings/channel/log-channels.js +0 -4
  194. package/dist/wirings/channel/pikku-abstract-channel-handler.js +6 -0
  195. package/dist/wirings/channel/serverless/serverless-channel-runner.js +2 -5
  196. package/dist/wirings/cli/channel/cli-approval.d.ts +41 -0
  197. package/dist/wirings/cli/channel/cli-approval.js +81 -0
  198. package/dist/wirings/cli/channel/cli-channel-runner.d.ts +0 -4
  199. package/dist/wirings/cli/channel/cli-channel-runner.js +3 -25
  200. package/dist/wirings/cli/channel/cli-raw-channel-runner.d.ts +47 -9
  201. package/dist/wirings/cli/channel/cli-raw-channel-runner.js +24 -16
  202. package/dist/wirings/cli/channel/cli-raw-client-runner.d.ts +38 -0
  203. package/dist/wirings/cli/channel/cli-raw-client-runner.js +129 -0
  204. package/dist/wirings/cli/channel/index.d.ts +5 -0
  205. package/dist/wirings/cli/channel/index.js +2 -0
  206. package/dist/wirings/cli/cli-runner.d.ts +20 -20
  207. package/dist/wirings/cli/cli-runner.js +28 -89
  208. package/dist/wirings/cli/cli.types.d.ts +14 -3
  209. package/dist/wirings/cli/command-parser.d.ts +1 -10
  210. package/dist/wirings/cli/command-parser.js +10 -87
  211. package/dist/wirings/cli/define-cli-commands.d.ts +1 -17
  212. package/dist/wirings/cli/define-cli-commands.js +1 -17
  213. package/dist/wirings/credential/credential.types.d.ts +0 -12
  214. package/dist/wirings/credential/define-credential.d.ts +48 -0
  215. package/dist/wirings/credential/define-credential.js +47 -0
  216. package/dist/wirings/credential/index.d.ts +1 -1
  217. package/dist/wirings/credential/index.js +1 -1
  218. package/dist/wirings/credential/validate-credential-definitions.d.ts +2 -4
  219. package/dist/wirings/gateway/gateway-runner.d.ts +1 -20
  220. package/dist/wirings/gateway/gateway-runner.js +8 -105
  221. package/dist/wirings/gateway/gateway.types.d.ts +7 -80
  222. package/dist/wirings/http/http-routes.d.ts +0 -63
  223. package/dist/wirings/http/http-routes.js +0 -63
  224. package/dist/wirings/http/http-runner.d.ts +0 -99
  225. package/dist/wirings/http/http-runner.js +9 -165
  226. package/dist/wirings/http/http.types.d.ts +14 -55
  227. package/dist/wirings/http/log-http-routes.d.ts +0 -4
  228. package/dist/wirings/http/log-http-routes.js +0 -4
  229. package/dist/wirings/http/pikku-fetch-http-request.d.ts +0 -40
  230. package/dist/wirings/http/pikku-fetch-http-request.js +0 -58
  231. package/dist/wirings/http/pikku-fetch-http-response.js +0 -3
  232. package/dist/wirings/http/routers/path-to-regex.js +2 -13
  233. package/dist/wirings/http/web-request.d.ts +0 -8
  234. package/dist/wirings/http/web-request.js +25 -17
  235. package/dist/wirings/mcp/mcp-runner.d.ts +1 -4
  236. package/dist/wirings/mcp/mcp-runner.js +1 -14
  237. package/dist/wirings/mcp/mcp.types.d.ts +2 -35
  238. package/dist/wirings/oauth2/oauth2.types.d.ts +0 -28
  239. package/dist/wirings/oauth2/oauth2.types.js +0 -3
  240. package/dist/wirings/persona/define-personas.d.ts +32 -0
  241. package/dist/wirings/persona/define-personas.js +31 -0
  242. package/dist/wirings/persona/index.d.ts +21 -0
  243. package/dist/wirings/persona/index.js +17 -0
  244. package/dist/wirings/persona/persona-email.d.ts +37 -0
  245. package/dist/wirings/persona/persona-email.js +69 -0
  246. package/dist/wirings/persona/persona-environments.d.ts +45 -0
  247. package/dist/wirings/persona/persona-environments.js +81 -0
  248. package/dist/wirings/persona/persona-mailbox.d.ts +101 -0
  249. package/dist/wirings/persona/persona-mailbox.js +53 -0
  250. package/dist/wirings/persona/persona.types.d.ts +136 -0
  251. package/dist/wirings/persona/persona.types.js +1 -0
  252. package/dist/wirings/persona/validate-personas.d.ts +53 -0
  253. package/dist/wirings/persona/validate-personas.js +94 -0
  254. package/dist/wirings/queue/index.d.ts +3 -0
  255. package/dist/wirings/queue/index.js +2 -3
  256. package/dist/wirings/queue/queue-identity.d.ts +28 -0
  257. package/dist/wirings/queue/queue-identity.js +103 -0
  258. package/dist/wirings/queue/queue-runner.d.ts +0 -19
  259. package/dist/wirings/queue/queue-runner.js +9 -30
  260. package/dist/wirings/queue/queue.types.d.ts +20 -90
  261. package/dist/wirings/queue/register-queue-helper.d.ts +0 -12
  262. package/dist/wirings/queue/register-queue-helper.js +0 -11
  263. package/dist/wirings/queue/signed-queue-service.d.ts +17 -0
  264. package/dist/wirings/queue/signed-queue-service.js +42 -0
  265. package/dist/wirings/queue/validate-worker-config.d.ts +2 -23
  266. package/dist/wirings/queue/validate-worker-config.js +0 -14
  267. package/dist/wirings/role/define-system-role.d.ts +32 -0
  268. package/dist/wirings/role/define-system-role.js +31 -0
  269. package/dist/wirings/role/index.d.ts +3 -0
  270. package/dist/wirings/role/index.js +2 -0
  271. package/dist/wirings/role/role.types.d.ts +43 -0
  272. package/dist/wirings/role/role.types.js +1 -0
  273. package/dist/wirings/role/validate-role-definitions.d.ts +21 -0
  274. package/dist/wirings/role/validate-role-definitions.js +71 -0
  275. package/dist/wirings/rpc/addon-runner.d.ts +0 -19
  276. package/dist/wirings/rpc/addon-runner.js +0 -51
  277. package/dist/wirings/rpc/remote-addon-auth.d.ts +3 -13
  278. package/dist/wirings/rpc/remote-addon-auth.js +7 -11
  279. package/dist/wirings/rpc/rpc-runner.d.ts +11 -18
  280. package/dist/wirings/rpc/rpc-runner.js +88 -105
  281. package/dist/wirings/rpc/rpc-types.d.ts +7 -6
  282. package/dist/wirings/rpc/wire-addon.d.ts +25 -0
  283. package/dist/wirings/rpc/wire-addon.js +62 -0
  284. package/dist/wirings/rpc/wire-remote-addon.d.ts +3 -28
  285. package/dist/wirings/rpc/wire-remote-addon.js +0 -8
  286. package/dist/wirings/scheduler/log-schedulers.d.ts +0 -4
  287. package/dist/wirings/scheduler/log-schedulers.js +0 -4
  288. package/dist/wirings/scheduler/scheduler-runner.d.ts +0 -1
  289. package/dist/wirings/scheduler/scheduler-runner.js +0 -1
  290. package/dist/wirings/scheduler/scheduler.types.d.ts +1 -14
  291. package/dist/wirings/scope/define-scope.d.ts +32 -0
  292. package/dist/wirings/scope/define-scope.js +31 -0
  293. package/dist/wirings/scope/index.d.ts +1 -1
  294. package/dist/wirings/scope/index.js +1 -1
  295. package/dist/wirings/scope/scope.types.d.ts +7 -9
  296. package/dist/wirings/scope/validate-scope-definitions.d.ts +2 -21
  297. package/dist/wirings/scope/validate-scope-definitions.js +3 -21
  298. package/dist/wirings/secret/index.d.ts +1 -1
  299. package/dist/wirings/secret/index.js +1 -1
  300. package/dist/wirings/secret/secret.types.d.ts +19 -15
  301. package/dist/wirings/secret/secret.types.js +1 -1
  302. package/dist/wirings/secret/validate-secret-definitions.d.ts +2 -4
  303. package/dist/wirings/trigger/trigger-runner.d.ts +0 -27
  304. package/dist/wirings/trigger/trigger-runner.js +1 -24
  305. package/dist/wirings/trigger/trigger.types.d.ts +1 -82
  306. package/dist/wirings/trigger/trigger.types.js +0 -34
  307. package/dist/wirings/variable/index.d.ts +1 -1
  308. package/dist/wirings/variable/index.js +1 -1
  309. package/dist/wirings/variable/validate-variable-definitions.d.ts +2 -4
  310. package/dist/wirings/variable/variable.types.d.ts +1 -13
  311. package/dist/wirings/variable/variable.types.js +1 -1
  312. package/dist/wirings/virtual-user/index.d.ts +30 -0
  313. package/dist/wirings/virtual-user/index.js +10 -0
  314. package/dist/wirings/virtual-user/prepare-virtual-user-run.d.ts +54 -0
  315. package/dist/wirings/virtual-user/prepare-virtual-user-run.js +49 -0
  316. package/dist/wirings/virtual-user/run-virtual-user.d.ts +92 -0
  317. package/dist/wirings/virtual-user/run-virtual-user.js +478 -0
  318. package/dist/wirings/virtual-user/virtual-user-agents.d.ts +38 -0
  319. package/dist/wirings/virtual-user/virtual-user-agents.js +24 -0
  320. package/dist/wirings/virtual-user/virtual-user-catalogue.d.ts +92 -0
  321. package/dist/wirings/virtual-user/virtual-user-catalogue.js +134 -0
  322. package/dist/wirings/virtual-user/virtual-user-derive.d.ts +26 -0
  323. package/dist/wirings/virtual-user/virtual-user-derive.js +137 -0
  324. package/dist/wirings/virtual-user/virtual-user-dispositions.d.ts +79 -0
  325. package/dist/wirings/virtual-user/virtual-user-dispositions.js +128 -0
  326. package/dist/wirings/virtual-user/virtual-user-intents.d.ts +78 -0
  327. package/dist/wirings/virtual-user/virtual-user-intents.js +142 -0
  328. package/dist/wirings/virtual-user/virtual-user-rng.d.ts +24 -0
  329. package/dist/wirings/virtual-user/virtual-user-rng.js +44 -0
  330. package/dist/wirings/virtual-user/virtual-user-run-store.d.ts +90 -0
  331. package/dist/wirings/virtual-user/virtual-user-run-store.js +1 -0
  332. package/dist/wirings/virtual-user/virtual-user-target.d.ts +21 -0
  333. package/dist/wirings/virtual-user/virtual-user-target.js +34 -0
  334. package/dist/wirings/virtual-user/virtual-user.types.d.ts +199 -0
  335. package/dist/wirings/virtual-user/virtual-user.types.js +8 -0
  336. package/dist/wirings/workflow/dsl/workflow-dsl.types.d.ts +19 -15
  337. package/dist/wirings/workflow/dsl/workflow-runner.d.ts +0 -4
  338. package/dist/wirings/workflow/dsl/workflow-runner.js +0 -4
  339. package/dist/wirings/workflow/feature.d.ts +0 -19
  340. package/dist/wirings/workflow/feature.js +0 -19
  341. package/dist/wirings/workflow/graph/graph-node.d.ts +0 -98
  342. package/dist/wirings/workflow/graph/graph-node.js +0 -34
  343. package/dist/wirings/workflow/graph/graph-runner.js +6 -41
  344. package/dist/wirings/workflow/graph/wire-workflow-graph.d.ts +0 -4
  345. package/dist/wirings/workflow/graph/workflow-graph.types.d.ts +0 -58
  346. package/dist/wirings/workflow/graph/workflow-graph.types.js +0 -6
  347. package/dist/wirings/workflow/index.d.ts +5 -7
  348. package/dist/wirings/workflow/index.js +3 -17
  349. package/dist/wirings/workflow/pikku-scenario-service.d.ts +87 -5
  350. package/dist/wirings/workflow/pikku-scenario-service.js +204 -43
  351. package/dist/wirings/workflow/pikku-workflow-service.d.ts +7 -459
  352. package/dist/wirings/workflow/pikku-workflow-service.js +58 -551
  353. package/dist/wirings/workflow/run-timeline.d.ts +0 -47
  354. package/dist/wirings/workflow/run-timeline.js +0 -22
  355. package/dist/wirings/workflow/scenario-cookie-jar.d.ts +0 -23
  356. package/dist/wirings/workflow/scenario-cookie-jar.js +0 -16
  357. package/dist/wirings/workflow/scenario-poll.d.ts +0 -15
  358. package/dist/wirings/workflow/scenario-poll.js +0 -12
  359. package/dist/wirings/workflow/scenario-prose.d.ts +0 -28
  360. package/dist/wirings/workflow/scenario-prose.js +1 -19
  361. package/dist/wirings/workflow/scenario-step-guards.d.ts +0 -13
  362. package/dist/wirings/workflow/scenario-step-guards.js +1 -14
  363. package/dist/wirings/workflow/scenario-step.types.d.ts +84 -12
  364. package/dist/wirings/workflow/scenario-step.types.js +5 -1
  365. package/dist/wirings/workflow/scenario-surface.d.ts +16 -0
  366. package/dist/wirings/workflow/scenario-surface.js +56 -0
  367. package/dist/wirings/workflow/workflow-invocation-id.d.ts +0 -18
  368. package/dist/wirings/workflow/workflow-invocation-id.js +2 -22
  369. package/dist/wirings/workflow/workflow-queue-workers.d.ts +0 -20
  370. package/dist/wirings/workflow/workflow-queue-workers.js +0 -19
  371. package/dist/wirings/workflow/workflow.types.d.ts +5 -195
  372. package/knowledge/decisions/index.md +19 -0
  373. package/knowledge/decisions/internals/a-secret-that-fails-to-decrypt-fails-the-whole-read.md +49 -0
  374. package/knowledge/decisions/internals/a-virtual-user-run-is-not-a-workflow-and-not-a-queued-job.md +48 -0
  375. package/knowledge/decisions/internals/actor-flow-conversations-seed-a-hidden-kickoff-message.md +23 -0
  376. package/knowledge/decisions/internals/actor-flow-drives-the-target-through-a-transport-seam.md +24 -0
  377. package/knowledge/decisions/internals/actor-flow-verdicts-are-llm-self-evaluations.md +25 -0
  378. package/knowledge/decisions/internals/addon-package-roots-resolve-by-walking-node-module-search-paths.md +26 -0
  379. package/knowledge/decisions/internals/addon-singleton-services-are-cached-per-namespace-not-per-package.md +33 -0
  380. package/knowledge/decisions/internals/addon-workflow-names-are-prefixed-with-the-consumer-namespace.md +28 -0
  381. package/knowledge/decisions/internals/ai-agent-agui-bridge-obeys-the-client-ordering-contract.md +29 -0
  382. package/knowledge/decisions/internals/ai-agent-audio-chunks-carry-the-format-the-provider-returned.md +20 -0
  383. package/knowledge/decisions/internals/ai-agent-credential-suspensions-hide-the-tool-result.md +26 -0
  384. package/knowledge/decisions/internals/ai-agent-delegate-and-supervise-hide-different-text.md +26 -0
  385. package/knowledge/decisions/internals/ai-agent-llm-tool-arguments-have-nulls-stripped.md +23 -0
  386. package/knowledge/decisions/internals/ai-agent-model-config-stays-a-single-resolution-seam.md +25 -0
  387. package/knowledge/decisions/internals/ai-agent-onerror-hooks-cannot-change-the-failure.md +22 -0
  388. package/knowledge/decisions/internals/ai-agent-runner-methods-must-keep-their-receiver.md +22 -0
  389. package/knowledge/decisions/internals/ai-agent-stream-persistence-is-best-effort.md +27 -0
  390. package/knowledge/decisions/internals/ai-agent-sub-agents-inherit-the-parent-context-block.md +26 -0
  391. package/knowledge/decisions/internals/ai-agent-tool-execute-failures-are-logged-unconditionally.md +25 -0
  392. package/knowledge/decisions/internals/ai-agent-voice-input-transcribes-audio-parts-in-place.md +22 -0
  393. package/knowledge/decisions/internals/ai-agent-working-memory-is-persisted-only-when-valid.md +25 -0
  394. package/knowledge/decisions/internals/channel-message-handlers-accept-three-config-shapes.md +30 -0
  395. package/knowledge/decisions/internals/channel-middleware-caches-only-statically-resolved-middleware.md +31 -0
  396. package/knowledge/decisions/internals/channel-state-is-per-socket-session-state-is-per-user.md +29 -0
  397. package/knowledge/decisions/internals/channel-user-id-is-persisted-after-onconnect-middleware-runs.md +28 -0
  398. package/knowledge/decisions/internals/cli-option-names-are-camelcase-in-state-and-kebab-on-the-command-line.md +27 -0
  399. package/knowledge/decisions/internals/cli-parse-errors-are-routed-by-message-prefix.md +28 -0
  400. package/knowledge/decisions/internals/cli-stdout-is-reserved-for-machine-readable-output.md +34 -0
  401. package/knowledge/decisions/internals/cli-unknown-long-options-warn-instead-of-failing.md +29 -0
  402. package/knowledge/decisions/internals/core-column-form-is-an-axis-of-its-own.md +84 -0
  403. package/knowledge/decisions/internals/core-data-classification-brand-is-an-optional-property.md +41 -0
  404. package/knowledge/decisions/internals/core-function-runner-restores-the-wire-fields-it-overwrites.md +44 -0
  405. package/knowledge/decisions/internals/core-hot-reload-merges-generated-meta-never-replaces-it.md +39 -0
  406. package/knowledge/decisions/internals/core-hot-reload-owns-its-module-registry.md +42 -0
  407. package/knowledge/decisions/internals/core-middleware-order-is-scope-then-priority.md +39 -0
  408. package/knowledge/decisions/internals/core-schema-defaults-apply-on-every-transport.md +43 -0
  409. package/knowledge/decisions/internals/core-scopes-are-an-and-gate-separate-from-permissions.md +38 -0
  410. package/knowledge/decisions/internals/core-state-is-a-global-map-written-only-at-registration-time.md +44 -0
  411. package/knowledge/decisions/internals/email-meta-is-read-uncached-because-codegen-rewrites-it-mid-session.md +27 -0
  412. package/knowledge/decisions/internals/gateway-adapters-resolve-lazily-and-are-promise-cached.md +32 -0
  413. package/knowledge/decisions/internals/gateway-webhook-challenges-echo-bytes-not-json.md +28 -0
  414. package/knowledge/decisions/internals/gateway-wiring-is-a-meta-wiring-over-http-and-channels.md +31 -0
  415. package/knowledge/decisions/internals/generated-src-paths-in-pikku-meta-are-absolute.md +26 -0
  416. package/knowledge/decisions/internals/http-request-bodies-are-read-once-and-shared.md +32 -0
  417. package/knowledge/decisions/internals/http-route-groups-cascade-config-in-a-fixed-order.md +28 -0
  418. package/knowledge/decisions/internals/http-router-matches-normalized-paths-but-returns-registered-ones.md +30 -0
  419. package/knowledge/decisions/internals/http-runner-logs-through-a-trace-scoped-logger-functions-do-not.md +26 -0
  420. package/knowledge/decisions/internals/http-set-cookie-headers-are-appended-never-joined.md +28 -0
  421. package/knowledge/decisions/internals/http-sse-streams-flush-headers-only-after-middleware.md +32 -0
  422. package/knowledge/decisions/internals/http-wiring-without-metadata-is-skipped-not-fatal.md +26 -0
  423. package/knowledge/decisions/internals/in-a-scenario-a-4xx-is-data-not-an-exception.md +25 -0
  424. package/knowledge/decisions/internals/in-memory-workflow-history-aliases-the-live-step-object.md +26 -0
  425. package/knowledge/decisions/internals/index.md +117 -0
  426. package/knowledge/decisions/internals/istanbul-statement-counts-attach-to-the-start-line-only.md +25 -0
  427. package/knowledge/decisions/internals/local-trigger-and-gateway-services-assume-a-single-process.md +26 -0
  428. package/knowledge/decisions/internals/node-only-builtins-are-imported-dynamically.md +24 -0
  429. package/knowledge/decisions/internals/one-project-shape-check-two-validators.md +53 -0
  430. package/knowledge/decisions/internals/queue-group-concurrency-keeps-one-shared-queue-fair.md +28 -0
  431. package/knowledge/decisions/internals/queue-jobs-always-carry-an-explicit-attempts-count.md +27 -0
  432. package/knowledge/decisions/internals/remote-addons-dispatch-over-http-instead-of-local-meta.md +31 -0
  433. package/knowledge/decisions/internals/rpc-names-resolve-through-package-scope-before-root.md +32 -0
  434. package/knowledge/decisions/internals/scenario-agent-calls-sign-in-on-401-only.md +27 -0
  435. package/knowledge/decisions/internals/scenario-meta-lives-apart-from-app-meta-but-merges-when-read-off-disk.md +26 -0
  436. package/knowledge/decisions/internals/scenario-steps-return-drained-response-records.md +27 -0
  437. package/knowledge/decisions/internals/scenarios-live-in-files-named-for-them.md +48 -0
  438. package/knowledge/decisions/internals/scope-roots-may-be-co-declared-by-an-addon-and-its-host-app.md +30 -0
  439. package/knowledge/decisions/internals/serverless-channel-disconnect-must-tolerate-a-missing-channel.md +28 -0
  440. package/knowledge/decisions/internals/the-dev-queue-copies-prod-timing-and-serialization-semantics.md +30 -0
  441. package/knowledge/decisions/internals/the-embedding-model-is-pinned-per-service-and-doc-query-embedding-is-split.md +29 -0
  442. package/knowledge/decisions/internals/the-in-memory-workflow-service-is-inline-only-and-single-process.md +27 -0
  443. package/knowledge/decisions/internals/the-kek-salt-is-scoped-to-the-key-version.md +40 -0
  444. package/knowledge/decisions/internals/the-schema-service-is-never-stubbed.md +26 -0
  445. package/knowledge/decisions/internals/trigger-declaration-is-split-from-trigger-source.md +33 -0
  446. package/knowledge/decisions/internals/typed-secret-service-caches-for-the-process-lifetime.md +26 -0
  447. package/knowledge/decisions/internals/validate-checks-personas-through-a-shared-module.md +43 -0
  448. package/knowledge/decisions/internals/webhook-delivery-history-records-every-attempt-best-effort.md +26 -0
  449. package/knowledge/decisions/internals/webhook-service-collaborators-are-constructor-args-not-locator-lookups.md +25 -0
  450. package/knowledge/decisions/internals/whether-a-run-is-inline-is-read-from-the-run-record.md +58 -0
  451. package/knowledge/decisions/internals/workflow-approval-expiry-is-decided-from-a-recorded-deadline.md +34 -0
  452. package/knowledge/decisions/internals/workflow-core-never-imports-a-browser-driver.md +42 -0
  453. package/knowledge/decisions/internals/workflow-dsl-meta-separates-runtime-expressions-from-literals.md +38 -0
  454. package/knowledge/decisions/internals/workflow-features-resolve-scenarios-by-object-identity.md +29 -0
  455. package/knowledge/decisions/internals/workflow-graph-inline-and-queued-runs-share-one-planner.md +42 -0
  456. package/knowledge/decisions/internals/workflow-graph-node-notes-are-excluded-from-the-graph-hash.md +25 -0
  457. package/knowledge/decisions/internals/workflow-inline-runs-report-their-run-id-before-they-can-fail.md +29 -0
  458. package/knowledge/decisions/internals/workflow-invocation-id-is-the-dedupe-key-not-step-id.md +43 -0
  459. package/knowledge/decisions/internals/workflow-queued-step-dispatch-requires-an-explicit-opt-in.md +29 -0
  460. package/knowledge/decisions/internals/workflow-queues-are-per-workflow-by-default.md +42 -0
  461. package/knowledge/decisions/internals/workflow-repeated-step-names-get-an-ordinal-suffix.md +33 -0
  462. package/knowledge/decisions/internals/workflow-replay-reads-its-steps-once-and-caches-only-the-immutable-half.md +32 -0
  463. package/knowledge/decisions/internals/workflow-retries-are-owned-by-the-workflow-not-the-queue.md +31 -0
  464. package/knowledge/decisions/internals/workflow-run-capabilities-are-extensions-not-subclasses.md +39 -0
  465. package/knowledge/decisions/internals/workflow-run-mirror-is-never-a-source-of-truth.md +29 -0
  466. package/knowledge/decisions/internals/workflow-run-polling-backs-off-to-the-callers-ceiling.md +33 -0
  467. package/knowledge/decisions/internals/workflow-run-timeline-is-a-pure-fold-over-durable-history.md +37 -0
  468. package/knowledge/decisions/internals/workflow-scenario-assertions-never-retry-and-record-one-step.md +50 -0
  469. package/knowledge/decisions/internals/workflow-scenario-hooks-are-a-scenario-only-affordance.md +43 -0
  470. package/knowledge/decisions/internals/workflow-scenario-prose-is-rendered-from-typed-calls-not-parsed-from-english.md +32 -0
  471. package/knowledge/decisions/internals/workflow-scenario-quarantine-reason-lives-in-code.md +18 -0
  472. package/knowledge/decisions/internals/workflow-scenario-step-targets-are-string-literals-for-the-inspector.md +34 -0
  473. package/knowledge/decisions/internals/workflow-step-compensation-runs-as-its-own-durable-step.md +26 -0
  474. package/knowledge/decisions/internals/workflow-step-dispatch-failure-is-transient-not-a-run-failure.md +33 -0
  475. package/knowledge/decisions/internals/workflow-step-lock-is-held-only-to-claim-the-step.md +27 -0
  476. package/knowledge/decisions/internals/workflow-step-rpc-name-is-provenance-only.md +34 -0
  477. package/knowledge/decisions/internals/workflow-suspend-and-approval-reasons-are-durable-step-identities.md +38 -0
  478. package/knowledge/decisions/internals/workflow-suspended-runs-keep-their-in-process-context.md +30 -0
  479. package/knowledge/decisions/security/a-dropped-audit-write-is-always-logged.md +26 -0
  480. package/knowledge/decisions/security/actor-flow-missing-approval-decisions-default-to-denied.md +22 -0
  481. package/knowledge/decisions/security/actor-sign-in-is-proven-by-set-cookie-not-a-non-empty-jar.md +27 -0
  482. package/knowledge/decisions/security/actor-sign-in-only-works-for-actor-flagged-users.md +27 -0
  483. package/knowledge/decisions/security/addon-auth-and-tags-only-tighten.md +43 -0
  484. package/knowledge/decisions/security/addon-config-gates-apply-only-at-the-namespaced-rpc-boundary.md +52 -0
  485. package/knowledge/decisions/security/addon-scopes-are-resolved-where-the-function-runs.md +46 -0
  486. package/knowledge/decisions/security/ai-agent-approval-forwarding-requires-a-symbol-brand.md +27 -0
  487. package/knowledge/decisions/security/ai-agent-credential-requests-are-symbol-branded.md +37 -0
  488. package/knowledge/decisions/security/ai-agent-gate-requires-a-session-only-when-auth-is-true.md +31 -0
  489. package/knowledge/decisions/security/ai-agent-ownership-failures-never-echo-the-resource.md +23 -0
  490. package/knowledge/decisions/security/ai-agent-resume-re-runs-the-authorization-gate.md +22 -0
  491. package/knowledge/decisions/security/ai-agent-sessionless-deployments-have-no-thread-ownership.md +39 -0
  492. package/knowledge/decisions/security/ai-agent-thread-ownership-composes-the-session-principal.md +30 -0
  493. package/knowledge/decisions/security/ai-agent-tool-filtering-reads-the-live-function-config.md +24 -0
  494. package/knowledge/decisions/security/an-empty-owners-constraint-matches-nothing.md +30 -0
  495. package/knowledge/decisions/security/an-exposed-ungated-function-is-a-codegen-warning.md +49 -0
  496. package/knowledge/decisions/security/console-addon-privileged-functions-gate-themselves.md +76 -0
  497. package/knowledge/decisions/security/core-safe-fetch-blocks-ssrf-by-host-literal-not-dns.md +39 -0
  498. package/knowledge/decisions/security/core-secrets-use-a-per-secret-dek-wrapped-by-a-kek.md +37 -0
  499. package/knowledge/decisions/security/gateway-handlers-run-through-the-function-runner-gate.md +31 -0
  500. package/knowledge/decisions/security/gateway-middleware-sessions-must-be-bridged-onto-the-wire.md +30 -0
  501. package/knowledge/decisions/security/global-permissions-and-function-permissions-are-independent-gates.md +40 -0
  502. package/knowledge/decisions/security/http-error-detail-is-withheld-from-clients-in-production.md +33 -0
  503. package/knowledge/decisions/security/http-request-bodies-are-bounded-before-they-are-buffered.md +46 -0
  504. package/knowledge/decisions/security/index.md +55 -0
  505. package/knowledge/decisions/security/mcp-internal-error-details-are-double-gated-on-production.md +27 -0
  506. package/knowledge/decisions/security/passphrases-are-stretched-key-material-is-expanded.md +40 -0
  507. package/knowledge/decisions/security/permission-auth-filtering-requires-live-permission-functions.md +31 -0
  508. package/knowledge/decisions/security/pikku-carries-actor-scopes-as-data-and-the-app-grants-them.md +26 -0
  509. package/knowledge/decisions/security/queue-job-identities-are-signed-at-enqueue.md +69 -0
  510. package/knowledge/decisions/security/queue-jobs-carry-the-producers-pikku-user-id.md +39 -0
  511. package/knowledge/decisions/security/remote-addon-tokens-are-client-credentials-not-mesh-trust.md +34 -0
  512. package/knowledge/decisions/security/scaffold-features-are-authenticated-unless-opted-out.md +49 -0
  513. package/knowledge/decisions/security/scenario-step-functions-are-never-externally-invocable.md +30 -0
  514. package/knowledge/decisions/security/scope-resolution-happens-at-the-session-boundary-and-sync-never-deletes.md +28 -0
  515. package/knowledge/decisions/security/self-authentication-is-declared-not-detected.md +34 -0
  516. package/knowledge/decisions/security/signed-content-urls-bind-the-request-path.md +37 -0
  517. package/knowledge/decisions/security/webhook-bodies-are-signed-before-they-are-enqueued.md +25 -0
  518. package/knowledge/decisions/security/workflow-actor-steps-always-use-the-real-transport.md +34 -0
  519. package/knowledge/decisions/security/workflow-approval-payloads-are-validated-on-replay-inside-the-workflow.md +40 -0
  520. package/knowledge/decisions/security/workflow-queued-steps-rehydrate-their-session-from-the-run-wire.md +32 -0
  521. package/knowledge/decisions/security/workflow-scenario-sessions-are-isolated-per-actor-and-per-scenario.md +32 -0
  522. package/knowledge/decisions/security/workflow-scenario-steps-are-never-network-invocable.md +31 -0
  523. package/knowledge/index.md +24 -0
  524. package/knowledge/questions/index.md +15 -0
  525. package/package.json +6 -2
  526. package/run-tests.sh +0 -0
  527. package/src/column-form.test.ts +97 -0
  528. package/src/column-form.ts +58 -0
  529. package/src/crypto-utils.test.ts +460 -19
  530. package/src/crypto-utils.ts +306 -59
  531. package/src/data-classification.ts +45 -7
  532. package/src/dev/hot-reload.test.ts +0 -4
  533. package/src/dev/hot-reload.ts +11 -30
  534. package/src/dev/module-runner.ts +7 -32
  535. package/src/dev/reload-meta.ts +9 -29
  536. package/src/errors/error-handler.ts +20 -35
  537. package/src/errors/error.test.ts +30 -1
  538. package/src/errors/errors.ts +73 -157
  539. package/src/function/abort-scope.test.ts +97 -0
  540. package/src/function/abort-scope.ts +80 -0
  541. package/src/function/function-runner.test.ts +0 -7
  542. package/src/function/function-runner.ts +62 -32
  543. package/src/function/functions.types.ts +95 -138
  544. package/src/function/index.ts +1 -0
  545. package/src/function/list.types.test.ts +3 -25
  546. package/src/function/list.types.ts +12 -62
  547. package/src/handle-error.ts +0 -18
  548. package/src/index.ts +84 -3
  549. package/src/middleware/auth-apikey.test.ts +0 -1
  550. package/src/middleware/auth-apikey.ts +0 -17
  551. package/src/middleware/auth-bearer.test.ts +3 -5
  552. package/src/middleware/auth-bearer.ts +5 -41
  553. package/src/middleware/auth-cookie.test.ts +0 -6
  554. package/src/middleware/auth-cookie.ts +2 -26
  555. package/src/middleware/cors.test.ts +34 -0
  556. package/src/middleware/cors.ts +12 -33
  557. package/src/middleware/remote-auth.test.ts +26 -10
  558. package/src/middleware/remote-auth.ts +11 -3
  559. package/src/middleware/telemetry.ts +2 -31
  560. package/src/middleware-runner.test.ts +0 -2
  561. package/src/middleware-runner.ts +5 -74
  562. package/src/permissions.test.ts +30 -0
  563. package/src/permissions.ts +24 -74
  564. package/src/pikku-request.ts +0 -6
  565. package/src/pikku-state.ts +2 -30
  566. package/src/production-barrels-stay-lean.test.ts +110 -0
  567. package/src/remote.test.ts +173 -0
  568. package/src/remote.ts +18 -8
  569. package/src/schema.ts +5 -39
  570. package/src/scopes.ts +7 -48
  571. package/src/secret-value.test.ts +204 -0
  572. package/src/secret-value.ts +111 -0
  573. package/src/services/ai-agent-runner-service.ts +20 -0
  574. package/src/services/ai-embedding-service.ts +3 -25
  575. package/src/services/audit-service.ts +88 -11
  576. package/src/services/content-service.ts +1 -46
  577. package/src/services/credential-service.ts +3 -40
  578. package/src/services/credential-wire-service.test.ts +0 -2
  579. package/src/services/credential-wire-service.ts +9 -1
  580. package/src/services/deployment-service.ts +3 -9
  581. package/src/services/email-service.ts +3 -1
  582. package/src/services/gateway-service.ts +0 -15
  583. package/src/services/{http-scenario-actors-converse.test.ts → http-personas-converse.test.ts} +38 -9
  584. package/src/services/{http-scenario-actors.test.ts → http-personas.test.ts} +39 -22
  585. package/src/services/{http-scenario-actors.ts → http-personas.ts} +85 -45
  586. package/src/services/in-memory-queue-service.ts +1 -15
  587. package/src/services/in-memory-trigger-service.ts +1 -18
  588. package/src/services/in-memory-workflow-service.test.ts +0 -13
  589. package/src/services/in-memory-workflow-service.ts +4 -38
  590. package/src/services/index.ts +23 -18
  591. package/src/services/istanbul-coverage-service.ts +2 -8
  592. package/src/services/jwt-service.ts +1 -16
  593. package/src/services/local-content-request-handler.test.ts +202 -0
  594. package/src/services/local-content-request-handler.ts +267 -0
  595. package/src/services/local-content.test.ts +159 -27
  596. package/src/services/local-content.ts +55 -23
  597. package/src/services/local-gateway-service.ts +2 -17
  598. package/src/services/local-secrets.test.ts +20 -5
  599. package/src/services/local-secrets.ts +15 -11
  600. package/src/services/logger-console.test.ts +0 -1
  601. package/src/services/logger-console.ts +3 -7
  602. package/src/services/logger.ts +31 -46
  603. package/src/services/meta-service.test.ts +1 -5
  604. package/src/services/meta-service.ts +41 -61
  605. package/src/services/{scenario-actors-service.ts → personas-service.ts} +48 -43
  606. package/src/services/pikku-user-id.ts +0 -4
  607. package/src/services/queue-webhook-service.test.ts +2 -1
  608. package/src/services/queue-webhook-service.ts +10 -42
  609. package/src/services/scheduler-service.ts +1 -50
  610. package/src/services/schema-service.ts +1 -24
  611. package/src/services/scope-service.ts +50 -34
  612. package/src/services/scoped-secret-service.ts +4 -7
  613. package/src/services/secret-host-binding.test.ts +138 -0
  614. package/src/services/secret-host-binding.ts +51 -0
  615. package/src/services/secret-service.ts +12 -35
  616. package/src/services/secretless.test.ts +54 -0
  617. package/src/services/secretless.ts +29 -0
  618. package/src/services/stub-tracker.ts +8 -18
  619. package/src/services/system-role-guard.test.ts +93 -0
  620. package/src/services/system-role-guard.ts +71 -0
  621. package/src/services/trigger-service.ts +0 -12
  622. package/src/services/typed-secret-service.ts +12 -14
  623. package/src/services/v8-coverage-service.ts +3 -6
  624. package/src/services/variables-service.ts +1 -8
  625. package/src/services/webhook-service.ts +23 -64
  626. package/src/services/workflow-service.ts +3 -20
  627. package/src/testing/service-tests.ts +6 -32
  628. package/src/time-utils.ts +1 -19
  629. package/src/types/core.types.ts +137 -229
  630. package/src/types/state.types.ts +7 -9
  631. package/src/utils/hmac.ts +4 -10
  632. package/src/utils/safe-fetch.ts +13 -54
  633. package/src/utils.test.ts +11 -2
  634. package/src/utils.ts +6 -15
  635. package/src/wirings/actor-flow/actor-flow.types.ts +1 -34
  636. package/src/wirings/actor-flow/index.ts +0 -9
  637. package/src/wirings/actor-flow/run-conversation.test.ts +11 -6
  638. package/src/wirings/actor-flow/run-conversation.ts +19 -12
  639. package/src/wirings/ai-agent/ai-agent-agui.test.ts +91 -10
  640. package/src/wirings/ai-agent/ai-agent-agui.ts +49 -17
  641. package/src/wirings/ai-agent/ai-agent-helpers.ts +20 -0
  642. package/src/wirings/ai-agent/ai-agent-interrupt.test.ts +842 -0
  643. package/src/wirings/ai-agent/ai-agent-interrupt.ts +399 -0
  644. package/src/wirings/ai-agent/ai-agent-memory.ts +0 -2
  645. package/src/wirings/ai-agent/ai-agent-model-config.ts +1 -9
  646. package/src/wirings/ai-agent/ai-agent-prepare.test.ts +202 -31
  647. package/src/wirings/ai-agent/ai-agent-prepare.ts +89 -139
  648. package/src/wirings/ai-agent/ai-agent-registry.test.ts +191 -6
  649. package/src/wirings/ai-agent/ai-agent-registry.ts +18 -1
  650. package/src/wirings/ai-agent/ai-agent-resume-authorization.test.ts +0 -2
  651. package/src/wirings/ai-agent/ai-agent-runner.test.ts +11 -9
  652. package/src/wirings/ai-agent/ai-agent-runner.ts +85 -35
  653. package/src/wirings/ai-agent/ai-agent-stream.test.ts +205 -103
  654. package/src/wirings/ai-agent/ai-agent-stream.ts +224 -76
  655. package/src/wirings/ai-agent/ai-agent-thread-ownership.test.ts +301 -0
  656. package/src/wirings/ai-agent/ai-agent.types.ts +130 -5
  657. package/src/wirings/ai-agent/index.ts +37 -3
  658. package/src/wirings/ai-agent/voice-input.test.ts +137 -7
  659. package/src/wirings/ai-agent/voice-input.ts +96 -12
  660. package/src/wirings/ai-agent/voice-output.test.ts +512 -0
  661. package/src/wirings/ai-agent/voice-output.ts +243 -56
  662. package/src/wirings/channel/channel-common.ts +15 -20
  663. package/src/wirings/channel/channel-handler.test.ts +50 -0
  664. package/src/wirings/channel/channel-handler.ts +32 -11
  665. package/src/wirings/channel/channel-host-rpc.test.ts +150 -0
  666. package/src/wirings/channel/channel-host-rpc.ts +69 -0
  667. package/src/wirings/channel/channel-middleware-runner.test.ts +0 -1
  668. package/src/wirings/channel/channel-middleware-runner.ts +0 -12
  669. package/src/wirings/channel/channel-rpc-registry.ts +116 -0
  670. package/src/wirings/channel/channel-rpc-responder.ts +117 -0
  671. package/src/wirings/channel/channel-rpc-service.ts +146 -0
  672. package/src/wirings/channel/channel-rpc-validators.ts +65 -0
  673. package/src/wirings/channel/channel-rpc.test.ts +820 -0
  674. package/src/wirings/channel/channel-rpc.ts +5 -0
  675. package/src/wirings/channel/channel-rpc.types.ts +150 -0
  676. package/src/wirings/channel/channel-runner.ts +0 -14
  677. package/src/wirings/channel/channel-store.ts +0 -10
  678. package/src/wirings/channel/channel.types.ts +19 -8
  679. package/src/wirings/channel/define-channel-routes.ts +0 -20
  680. package/src/wirings/channel/eventhub-service.ts +0 -18
  681. package/src/wirings/channel/index.ts +35 -0
  682. package/src/wirings/channel/local/local-channel-handler.ts +3 -1
  683. package/src/wirings/channel/local/local-channel-runner.test.ts +0 -10
  684. package/src/wirings/channel/local/local-channel-runner.ts +3 -1
  685. package/src/wirings/channel/local/local-eventhub-service.test.ts +0 -13
  686. package/src/wirings/channel/local/local-eventhub-service.ts +2 -37
  687. package/src/wirings/channel/log-channels.ts +0 -4
  688. package/src/wirings/channel/pikku-abstract-channel-handler.test.ts +83 -2
  689. package/src/wirings/channel/pikku-abstract-channel-handler.ts +7 -0
  690. package/src/wirings/channel/serverless/serverless-channel-runner.ts +2 -5
  691. package/src/wirings/cli/channel/cli-approval.test.ts +177 -0
  692. package/src/wirings/cli/channel/cli-approval.ts +135 -0
  693. package/src/wirings/cli/channel/cli-channel-runner.ts +4 -26
  694. package/src/wirings/cli/channel/cli-raw-channel-runner.test.ts +169 -0
  695. package/src/wirings/cli/channel/cli-raw-channel-runner.ts +59 -16
  696. package/src/wirings/cli/channel/cli-raw-client-runner.test.ts +480 -0
  697. package/src/wirings/cli/channel/cli-raw-client-runner.ts +185 -0
  698. package/src/wirings/cli/channel/index.ts +13 -0
  699. package/src/wirings/cli/cli-runner.test.ts +0 -1
  700. package/src/wirings/cli/cli-runner.ts +46 -88
  701. package/src/wirings/cli/cli.types.ts +14 -3
  702. package/src/wirings/cli/command-parser.test.ts +0 -4
  703. package/src/wirings/cli/command-parser.ts +11 -91
  704. package/src/wirings/cli/define-cli-commands.ts +1 -17
  705. package/src/wirings/credential/credential.types.ts +0 -12
  706. package/src/wirings/credential/{wire-credential.ts → define-credential.ts} +7 -7
  707. package/src/wirings/credential/index.ts +1 -1
  708. package/src/wirings/credential/validate-credential-definitions.ts +2 -4
  709. package/src/wirings/gateway/gateway-runner.test.ts +1 -21
  710. package/src/wirings/gateway/gateway-runner.ts +8 -110
  711. package/src/wirings/gateway/gateway.types.ts +7 -80
  712. package/src/wirings/http/http-routes.test.ts +0 -3
  713. package/src/wirings/http/http-routes.ts +0 -86
  714. package/src/wirings/http/http-runner.test.ts +0 -1
  715. package/src/wirings/http/http-runner.ts +8 -167
  716. package/src/wirings/http/http.types.ts +15 -62
  717. package/src/wirings/http/log-http-routes.ts +0 -4
  718. package/src/wirings/http/pikku-fetch-http-request.test.ts +2 -10
  719. package/src/wirings/http/pikku-fetch-http-request.ts +0 -58
  720. package/src/wirings/http/pikku-fetch-http-response.test.ts +1 -1
  721. package/src/wirings/http/pikku-fetch-http-response.ts +0 -3
  722. package/src/wirings/http/routers/path-to-regex.test.ts +4 -17
  723. package/src/wirings/http/routers/path-to-regex.ts +2 -13
  724. package/src/wirings/http/web-request.test.ts +33 -2
  725. package/src/wirings/http/web-request.ts +30 -17
  726. package/src/wirings/mcp/mcp-endpoint-registry.test.ts +0 -1
  727. package/src/wirings/mcp/mcp-runner.ts +2 -17
  728. package/src/wirings/mcp/mcp.types.ts +7 -42
  729. package/src/wirings/oauth2/oauth2.types.ts +0 -30
  730. package/src/wirings/persona/define-personas.ts +33 -0
  731. package/src/wirings/persona/index.ts +62 -0
  732. package/src/wirings/persona/persona-email.ts +87 -0
  733. package/src/wirings/persona/persona-environments.test.ts +183 -0
  734. package/src/wirings/persona/persona-environments.ts +138 -0
  735. package/src/wirings/persona/persona-mailbox.ts +156 -0
  736. package/src/wirings/persona/persona.test.ts +220 -0
  737. package/src/wirings/persona/persona.types.ts +142 -0
  738. package/src/wirings/persona/validate-personas.ts +133 -0
  739. package/src/wirings/queue/index.ts +13 -3
  740. package/src/wirings/queue/queue-identity.test.ts +454 -0
  741. package/src/wirings/queue/queue-identity.ts +176 -0
  742. package/src/wirings/queue/queue-runner.ts +12 -31
  743. package/src/wirings/queue/queue.types.ts +25 -90
  744. package/src/wirings/queue/register-queue-helper.ts +0 -14
  745. package/src/wirings/queue/signed-queue-service.ts +60 -0
  746. package/src/wirings/queue/validate-worker-config.ts +2 -28
  747. package/src/wirings/role/define-system-role.ts +33 -0
  748. package/src/wirings/role/index.ts +13 -0
  749. package/src/wirings/role/role.test.ts +104 -0
  750. package/src/wirings/role/role.types.ts +47 -0
  751. package/src/wirings/role/validate-role-definitions.ts +93 -0
  752. package/src/wirings/rpc/addon-auth-tags.test.ts +223 -0
  753. package/src/wirings/rpc/addon-runner.ts +0 -56
  754. package/src/wirings/rpc/addon-scopes.test.ts +225 -0
  755. package/src/wirings/rpc/remote-addon-auth.ts +9 -16
  756. package/src/wirings/rpc/rpc-runner.test.ts +192 -6
  757. package/src/wirings/rpc/rpc-runner.ts +145 -127
  758. package/src/wirings/rpc/rpc-types.ts +11 -6
  759. package/src/wirings/rpc/wire-addon.test.ts +43 -1
  760. package/src/wirings/rpc/wire-addon.ts +99 -0
  761. package/src/wirings/rpc/wire-remote-addon.ts +9 -29
  762. package/src/wirings/scheduler/log-schedulers.ts +0 -4
  763. package/src/wirings/scheduler/scheduler-runner.test.ts +1 -8
  764. package/src/wirings/scheduler/scheduler-runner.ts +0 -2
  765. package/src/wirings/scheduler/scheduler.types.ts +1 -14
  766. package/src/wirings/scope/{wire-scope.ts → define-scope.ts} +5 -6
  767. package/src/wirings/scope/index.ts +1 -1
  768. package/src/wirings/scope/scope.test.ts +1 -2
  769. package/src/wirings/scope/scope.types.ts +7 -9
  770. package/src/wirings/scope/validate-scope-definitions.ts +3 -21
  771. package/src/wirings/secret/index.ts +1 -1
  772. package/src/wirings/secret/secret.types.ts +19 -15
  773. package/src/wirings/secret/validate-secret-definitions.ts +2 -4
  774. package/src/wirings/trigger/trigger-runner.ts +1 -27
  775. package/src/wirings/trigger/trigger.types.ts +1 -82
  776. package/src/wirings/variable/index.ts +1 -1
  777. package/src/wirings/variable/validate-variable-definitions.ts +2 -4
  778. package/src/wirings/variable/variable.types.ts +1 -13
  779. package/src/wirings/virtual-user/index.ts +88 -0
  780. package/src/wirings/virtual-user/prepare-virtual-user-run.test.ts +115 -0
  781. package/src/wirings/virtual-user/prepare-virtual-user-run.ts +95 -0
  782. package/src/wirings/virtual-user/run-virtual-user.test.ts +765 -0
  783. package/src/wirings/virtual-user/run-virtual-user.ts +671 -0
  784. package/src/wirings/virtual-user/virtual-user-agents.test.ts +65 -0
  785. package/src/wirings/virtual-user/virtual-user-agents.ts +57 -0
  786. package/src/wirings/virtual-user/virtual-user-catalogue.test.ts +215 -0
  787. package/src/wirings/virtual-user/virtual-user-catalogue.ts +184 -0
  788. package/src/wirings/virtual-user/virtual-user-derive.test.ts +398 -0
  789. package/src/wirings/virtual-user/virtual-user-derive.ts +173 -0
  790. package/src/wirings/virtual-user/virtual-user-dispositions.test.ts +63 -0
  791. package/src/wirings/virtual-user/virtual-user-dispositions.ts +213 -0
  792. package/src/wirings/virtual-user/virtual-user-intents.test.ts +208 -0
  793. package/src/wirings/virtual-user/virtual-user-intents.ts +185 -0
  794. package/src/wirings/virtual-user/virtual-user-rng.test.ts +72 -0
  795. package/src/wirings/virtual-user/virtual-user-rng.ts +50 -0
  796. package/src/wirings/virtual-user/virtual-user-run-store.ts +98 -0
  797. package/src/wirings/virtual-user/virtual-user-target.ts +47 -0
  798. package/src/wirings/virtual-user/virtual-user.types.ts +219 -0
  799. package/src/wirings/workflow/dsl/workflow-dsl.types.ts +19 -20
  800. package/src/wirings/workflow/dsl/workflow-runner.ts +0 -4
  801. package/src/wirings/workflow/feature.ts +0 -19
  802. package/src/wirings/workflow/graph/graph-node.ts +0 -136
  803. package/src/wirings/workflow/graph/graph-runner.test.ts +20 -19
  804. package/src/wirings/workflow/graph/graph-runner.ts +6 -41
  805. package/src/wirings/workflow/graph/wire-workflow-graph.ts +0 -4
  806. package/src/wirings/workflow/graph/workflow-graph.types.ts +0 -58
  807. package/src/wirings/workflow/index.ts +10 -44
  808. package/src/wirings/workflow/pikku-scenario-service.ts +235 -61
  809. package/src/wirings/workflow/pikku-workflow-service.test.ts +0 -39
  810. package/src/wirings/workflow/pikku-workflow-service.ts +77 -674
  811. package/src/wirings/workflow/run-timeline.test.ts +7 -19
  812. package/src/wirings/workflow/run-timeline.ts +0 -56
  813. package/src/wirings/workflow/scenario-cookie-jar.test.ts +0 -1
  814. package/src/wirings/workflow/scenario-cookie-jar.ts +0 -25
  815. package/src/wirings/workflow/scenario-expectations.test.ts +2 -7
  816. package/src/wirings/workflow/scenario-hooks.test.ts +2 -7
  817. package/src/wirings/workflow/scenario-poll.test.ts +0 -2
  818. package/src/wirings/workflow/scenario-poll.ts +0 -15
  819. package/src/wirings/workflow/scenario-prose.test.ts +5 -7
  820. package/src/wirings/workflow/scenario-prose.ts +1 -29
  821. package/src/wirings/workflow/scenario-service.test.ts +2 -10
  822. package/src/wirings/workflow/scenario-step-guards.ts +1 -14
  823. package/src/wirings/workflow/scenario-step.test.ts +163 -19
  824. package/src/wirings/workflow/scenario-step.types.ts +94 -12
  825. package/src/wirings/workflow/scenario-surface.test.ts +146 -0
  826. package/src/wirings/workflow/scenario-surface.ts +71 -0
  827. package/src/wirings/workflow/workflow-dispatch-durability.test.ts +14 -15
  828. package/src/wirings/workflow/workflow-dispatch-payload.test.ts +0 -4
  829. package/src/wirings/workflow/workflow-inline-authority.test.ts +169 -0
  830. package/src/wirings/workflow/workflow-invocation-id.test.ts +0 -2
  831. package/src/wirings/workflow/workflow-invocation-id.ts +2 -22
  832. package/src/wirings/workflow/workflow-mirror.test.ts +0 -7
  833. package/src/wirings/workflow/workflow-on-error.test.ts +0 -9
  834. package/src/wirings/workflow/workflow-queue-workers.ts +0 -21
  835. package/src/wirings/workflow/workflow-replay-snapshot.test.ts +8 -7
  836. package/src/wirings/workflow/workflow-retry-policy.test.ts +0 -5
  837. package/src/wirings/workflow/workflow-run-context.test.ts +5 -10
  838. package/src/wirings/workflow/workflow-run-polling.test.ts +0 -5
  839. package/src/wirings/workflow/workflow-step-ordinal.test.ts +19 -4
  840. package/src/wirings/workflow/workflow-step-session.test.ts +0 -7
  841. package/src/wirings/workflow/workflow.types.ts +5 -201
  842. package/tsconfig.tsbuildinfo +1 -1
  843. package/tsconfig.type-tests.json +12 -0
  844. package/src/middleware/timeout.ts +0 -22
  845. package/src/pikku-response.ts +0 -5
  846. package/src/wirings/mcp/mcp-endpoint-registry.test.d.ts +0 -1
  847. package/src/wirings/workflow/dsl/index.ts +0 -36
  848. package/src/wirings/workflow/graph/index.ts +0 -15
@@ -1,8 +1,9 @@
1
1
  import type { AIStreamChannel } from './ai-agent.types.js';
2
2
  import type { AIAgentRunnerParams, AIAgentStepResult } from '../../services/ai-agent-runner-service.js';
3
3
  import { ToolApprovalRequired, ToolCredentialRequired, type RunAIAgentParams, type StreamAIAgentOptions } from './ai-agent-prepare.js';
4
- export declare function checkForApprovals(stepResult: AIAgentStepResult, tools: AIAgentRunnerParams['tools'], runId: string): ToolApprovalRequired[];
5
- export declare function checkForCredentialRequests(stepResult: AIAgentStepResult, runId: string): ToolCredentialRequired[];
4
+ import { type AgentInterruption, type AgentInterruptResult } from './ai-agent-interrupt.js';
5
+ export declare function checkForApprovals(stepResult: AIAgentStepResult, tools: AIAgentRunnerParams['tools']): ToolApprovalRequired[];
6
+ export declare function checkForCredentialRequests(stepResult: AIAgentStepResult): ToolCredentialRequired[];
6
7
  export declare function appendStepMessages(runnerParams: AIAgentRunnerParams, stepResult: AIAgentStepResult): void;
7
8
  export declare function streamAIAgent(agentName: string, input: {
8
9
  message: string;
@@ -11,6 +12,28 @@ export declare function streamAIAgent(agentName: string, input: {
11
12
  model?: string;
12
13
  temperature?: number;
13
14
  }, channel: AIStreamChannel, params: RunAIAgentParams, agentSessionMap?: Map<string, string>, options?: StreamAIAgentOptions): Promise<string>;
15
+ /**
16
+ * Stop an in-flight run on behalf of a caller, after checking the run is theirs.
17
+ *
18
+ * Unlike {@link resumeAIAgent} this needs no channel: it does not continue the
19
+ * stream, it ends one. The `interrupted` event and the truncated message are
20
+ * emitted by the original {@link streamAIAgent} call on its own channel, so this
21
+ * can be reached over a plain RPC while the stream is held open elsewhere —
22
+ * which is exactly the shape a voice barge-in needs.
23
+ *
24
+ * Ownership is the whole gate, deliberately without {@link assertAgentAuthorized}.
25
+ * Resuming re-enters the agent and approves a tool call, so a revoked grant must
26
+ * block it; stopping is the opposite — if a caller's access to an agent was
27
+ * revoked mid-run, being able to stop their own run is harmless and arguably
28
+ * what you want.
29
+ *
30
+ * Returns `false` when there was nothing to stop. Racing a run that finishes on
31
+ * its own is the normal case in voice, so it is not an error.
32
+ */
33
+ export declare function interruptAIAgent(input: {
34
+ runId: string;
35
+ reason?: AgentInterruption['reason'];
36
+ }, params: RunAIAgentParams): Promise<AgentInterruptResult>;
14
37
  export declare function resumeAIAgent(input: {
15
38
  runId: string;
16
39
  toolCallId: string;
@@ -1,10 +1,12 @@
1
1
  import { pikkuState, getSingletonServices } from '../../pikku-state.js';
2
2
  import { AIProviderNotConfiguredError } from '../../errors/errors.js';
3
3
  import { randomUUID } from './ai-agent-utils.js';
4
+ import { SPOKEN_TRANSCRIPT } from './voice-input.js';
4
5
  import { combineChannelMiddleware, wrapChannelWithMiddleware, } from '../channel/channel-middleware-runner.js';
5
6
  import { resolveMemoryServices, loadContextMessages, trimMessages, getWorkingMemoryMiddleware, } from './ai-agent-memory.js';
6
- import { prepareAgentRun, resolveAgent, buildInstructions, buildToolDefs, createScopedChannel, resolveOwnerResourceId, agentSessionScope, assertResourceOwner, assertAgentAuthorized, ToolApprovalRequired, ToolCredentialRequired, APPROVAL_REQUIRED, } from './ai-agent-prepare.js';
7
+ import { prepareAgentRun, resolveAgent, buildInstructions, buildToolDefs, createScopedChannel, resolveOwnerResourceId, agentSessionScope, assertResourceOwner, assertResourcePrincipalOwner, assertAgentAuthorized, ToolApprovalRequired, ToolCredentialRequired, APPROVAL_REQUIRED, CREDENTIAL_REQUIRED, } from './ai-agent-prepare.js';
7
8
  import { resolveModelConfig } from './ai-agent-model-config.js';
9
+ import { getInFlightTools, isAbortError, persistOrphanedToolResults, registerInterruptibleRun, signalRunInterrupt, trackInterruptNote, trackToolExecution, } from './ai-agent-interrupt.js';
8
10
  function createPersistingChannel(parent, storage, threadId, logger) {
9
11
  let fullText = '';
10
12
  let stepText = '';
@@ -15,7 +17,7 @@ function createPersistingChannel(parent, storage, threadId, logger) {
15
17
  inputTokens: 0,
16
18
  outputTokens: 0,
17
19
  };
18
- const flushStep = async () => {
20
+ const flushStep = async (opts) => {
19
21
  if (!storage)
20
22
  return;
21
23
  const text = stepText;
@@ -37,6 +39,7 @@ function createPersistingChannel(parent, storage, threadId, logger) {
37
39
  ]
38
40
  : text || undefined,
39
41
  toolCalls: calls.length > 0 ? calls : undefined,
42
+ ...(opts?.interrupted ? { interrupted: true } : {}),
40
43
  createdAt: new Date(),
41
44
  };
42
45
  const messages = [assistantMsg];
@@ -51,14 +54,6 @@ function createPersistingChannel(parent, storage, threadId, logger) {
51
54
  await storage.saveMessages(threadId, messages);
52
55
  }
53
56
  };
54
- /**
55
- * `send` is synchronous and so cannot await the flush. A rejection would have
56
- * nothing to propagate to and would take the process down as an unhandled
57
- * rejection — a model reusing a toolCallId, which is a primary key in AI
58
- * storage, is enough to trigger it. Persistence from inside `send` is
59
- * therefore best-effort: the run carries on, and the awaited `flush()` on the
60
- * suspend paths still surfaces failures to its caller.
61
- */
62
57
  const flushDetached = () => {
63
58
  void flushStep().catch((error) => {
64
59
  logger?.error('Failed to persist agent messages', {
@@ -83,11 +78,15 @@ function createPersistingChannel(parent, storage, threadId, logger) {
83
78
  close: () => parent.close(),
84
79
  sendBinary: (data) => parent.sendBinary(data),
85
80
  send: (event) => {
81
+ // Accumulated whether or not storage is configured: `fullText` is what
82
+ // the client was streamed, and an interrupted run has to be able to
83
+ // report the fragment it got through even with persistence turned off.
84
+ if (event.type === 'text-delta')
85
+ fullText += event.text;
86
86
  if (storage) {
87
87
  switch (event.type) {
88
88
  case 'text-delta':
89
89
  stepText += event.text;
90
- fullText += event.text;
91
90
  break;
92
91
  case 'tool-call':
93
92
  stepToolCalls.push({
@@ -125,6 +124,7 @@ function createPersistingChannel(parent, storage, threadId, logger) {
125
124
  setState: (s) => parent.setState(s),
126
125
  getState: () => parent.getState(),
127
126
  clearState: () => parent.clearState(),
127
+ remote: (funcName, data) => parent.remote(funcName, data),
128
128
  };
129
129
  return channel;
130
130
  }
@@ -161,7 +161,7 @@ async function postStreamCleanup(persistingChannel, aiMiddlewares, singletonServ
161
161
  });
162
162
  }
163
163
  async function runStreamStepLoop(params) {
164
- const { agent, runnerParams, maxSteps, agentRunner, streamChannel, channel, runId, aiMiddlewares, } = params;
164
+ const { agent, runnerParams, maxSteps, agentRunner, streamChannel, channel, aiMiddlewares, } = params;
165
165
  const singletonServices = getSingletonServices();
166
166
  for (let step = 0; step < maxSteps; step++) {
167
167
  if (agent.prepareStep) {
@@ -195,25 +195,21 @@ async function runStreamStepLoop(params) {
195
195
  }
196
196
  if (stepResult.toolCalls.length === 0)
197
197
  break;
198
- const approvalsNeeded = checkForApprovals(stepResult, runnerParams.tools, runId);
198
+ const approvalsNeeded = checkForApprovals(stepResult, runnerParams.tools);
199
199
  if (approvalsNeeded.length > 0) {
200
- // For each approval, call approvalDescriptionFn if available
201
200
  for (const approval of approvalsNeeded) {
202
201
  const toolDef = runnerParams.tools.find((t) => t.name === approval.toolName);
203
202
  if (toolDef?.approvalDescriptionFn && !approval.reason) {
204
203
  try {
205
204
  approval.reason = await toolDef.approvalDescriptionFn(approval.args);
206
205
  }
207
- catch {
208
- // If description generation fails, continue without it
209
- }
206
+ catch { }
210
207
  }
211
208
  }
212
209
  return { outcome: 'approval', approvals: approvalsNeeded };
213
210
  }
214
- const credentialRequests = checkForCredentialRequests(stepResult, runId);
211
+ const credentialRequests = checkForCredentialRequests(stepResult);
215
212
  if (credentialRequests.length > 0) {
216
- // Append step messages so the tool result is preserved for resume
217
213
  appendStepMessages(runnerParams, stepResult);
218
214
  return { outcome: 'credential', credentialRequests };
219
215
  }
@@ -221,7 +217,7 @@ async function runStreamStepLoop(params) {
221
217
  }
222
218
  return { outcome: 'done' };
223
219
  }
224
- export function checkForApprovals(stepResult, tools, runId) {
220
+ export function checkForApprovals(stepResult, tools) {
225
221
  const approvals = [];
226
222
  for (const tc of stepResult.toolCalls) {
227
223
  const toolDef = tools.find((t) => t.name === tc.toolName);
@@ -229,12 +225,6 @@ export function checkForApprovals(stepResult, tools, runId) {
229
225
  approvals.push(new ToolApprovalRequired(tc.toolCallId, tc.toolName, tc.args));
230
226
  continue;
231
227
  }
232
- // The approval marker is only trusted from a framework tool declared with
233
- // `forwardsApproval` (the sub-agent delegating tools) AND carrying the
234
- // non-forgeable `APPROVAL_REQUIRED` Symbol brand. A plain tool's output — or
235
- // a delegating tool's LLM-shaped `result.object`, which an attacker can
236
- // influence — is plain JSON and can never carry the Symbol, so it can never
237
- // forge an approval/suspension.
238
228
  if (!toolDef?.forwardsApproval) {
239
229
  continue;
240
230
  }
@@ -255,12 +245,13 @@ export function checkForApprovals(stepResult, tools, runId) {
255
245
  }
256
246
  return approvals;
257
247
  }
258
- export function checkForCredentialRequests(stepResult, runId) {
248
+ export function checkForCredentialRequests(stepResult) {
259
249
  const requests = [];
260
250
  for (const tr of stepResult.toolResults) {
251
+ // knowledge: decisions/security/ai-agent-credential-requests-are-symbol-branded.md
261
252
  if (tr.result &&
262
253
  typeof tr.result === 'object' &&
263
- '__credentialRequired' in tr.result) {
254
+ CREDENTIAL_REQUIRED in tr.result) {
264
255
  const r = tr.result;
265
256
  const tc = stepResult.toolCalls.find((t) => t.toolCallId === tr.toolCallId);
266
257
  requests.push(new ToolCredentialRequired(tr.toolCallId, tc?.toolName ?? 'unknown', tc?.args ?? {}, r.credentialName, r.credentialType, r.connectUrl));
@@ -366,10 +357,6 @@ function handleCredentialRequests(requests, runId, channel, aiRunState, persisti
366
357
  suspendReason: 'credential',
367
358
  pendingApprovals,
368
359
  });
369
- // The __credentialRequired tool result is suppressed from the stream, so
370
- // credential-request events (with the runId needed for /resume) are the
371
- // client's signal to show Connect/Ignore buttons — mirroring how
372
- // approval-request suspensions work.
373
360
  for (const req of requests) {
374
361
  channel.send({
375
362
  type: 'credential-request',
@@ -393,7 +380,6 @@ export async function streamAIAgent(agentName, input, channel, params, agentSess
393
380
  resourceId: resolveOwnerResourceId(params, agentSessionScope(agentName), input.resourceId),
394
381
  };
395
382
  const streamContext = { channel, options };
396
- // delegateState is attached after prepareAgentRun resolves the agent config
397
383
  const { agent, packageName, resolvedName, agentRunner, storage, memoryConfig, threadId, userMessage, runnerParams, maxSteps, missingRpcs, workingMemorySchemaName, } = await prepareAgentRun(agentName, normalizedInput, params, sessionMap, streamContext);
398
384
  runnerParams.agentId = agentName;
399
385
  const singletonServices = getSingletonServices();
@@ -426,6 +412,8 @@ export async function streamAIAgent(agentName, input, channel, params, agentSess
426
412
  }),
427
413
  ...(agent.aiMiddleware ?? []),
428
414
  ];
415
+ // One bag per run, shared by every middleware — see PikkuAIMiddlewareHooks.
416
+ const sharedNotes = {};
429
417
  let modifiedMessages = runnerParams.messages;
430
418
  let modifiedInstructions = runnerParams.instructions;
431
419
  for (const mw of aiMiddlewares) {
@@ -433,6 +421,7 @@ export async function streamAIAgent(agentName, input, channel, params, agentSess
433
421
  const result = await mw.modifyInput(singletonServices, {
434
422
  messages: modifiedMessages,
435
423
  instructions: modifiedInstructions,
424
+ shared: sharedNotes,
436
425
  });
437
426
  modifiedMessages = result.messages;
438
427
  modifiedInstructions = result.instructions;
@@ -440,6 +429,23 @@ export async function streamAIAgent(agentName, input, channel, params, agentSess
440
429
  }
441
430
  runnerParams.messages = modifiedMessages;
442
431
  runnerParams.instructions = modifiedInstructions;
432
+ // Sent on the raw channel, ahead of the run. A voice client sent audio and so
433
+ // has no idea what it said; until this arrives its own message is a blank
434
+ // bubble. Ahead of the run rather than alongside it because the answer starts
435
+ // streaming within a few hundred milliseconds, and a question that appears
436
+ // after its answer reads as the wrong question.
437
+ const transcript = sharedNotes[SPOKEN_TRANSCRIPT];
438
+ if (typeof transcript === 'string') {
439
+ channel.send({ type: 'transcript', text: transcript });
440
+ }
441
+ // What goes into thread history is what the model was actually asked. For a
442
+ // spoken turn that is not what arrived over the wire: the wire carried a
443
+ // base64 audio blob, and persisting it would write megabytes of unreadable
444
+ // data into the history while losing the only readable record of the turn.
445
+ // Identity-checked rather than assumed — a middleware is free to rewrite the
446
+ // message list into something with no relation to the turn.
447
+ const lastModified = modifiedMessages[modifiedMessages.length - 1];
448
+ const persistedUserMessage = lastModified?.id === userMessage.id ? lastModified : userMessage;
443
449
  const runId = await aiRunState.createRun({
444
450
  agentName,
445
451
  threadId,
@@ -450,8 +456,14 @@ export async function streamAIAgent(agentName, input, channel, params, agentSess
450
456
  updatedAt: new Date(),
451
457
  });
452
458
  options?.onRunCreated?.(runId);
459
+ // Registered before the first model call and released in `finally`, so the
460
+ // window in which an interrupt can land is exactly the window in which there
461
+ // is something to interrupt.
462
+ const interruptHandle = registerInterruptibleRun(runId);
463
+ runnerParams.abortSignal = interruptHandle.signal;
464
+ runnerParams.tools = trackToolExecution(runnerParams.tools, interruptHandle);
453
465
  if (storage) {
454
- await storage.saveMessages(threadId, [userMessage]);
466
+ await storage.saveMessages(threadId, [persistedUserMessage]);
455
467
  }
456
468
  const streamMiddleware = aiMiddlewares
457
469
  .filter((mw) => mw.modifyOutputStream)
@@ -464,6 +476,11 @@ export async function streamAIAgent(agentName, input, channel, params, agentSess
464
476
  event,
465
477
  allEvents,
466
478
  state,
479
+ shared: sharedNotes,
480
+ // Sends downstream directly, so a hook can hand back the fast event
481
+ // now and push the slow one when it is ready.
482
+ emit: next,
483
+ signal: interruptHandle.signal,
467
484
  });
468
485
  if (result == null)
469
486
  return;
@@ -489,12 +506,12 @@ export async function streamAIAgent(agentName, input, channel, params, agentSess
489
506
  const wrappedChannel = allChannelMiddleware.length > 0
490
507
  ? wrapChannelWithMiddleware({ channel: persistingChannel }, singletonServices, allChannelMiddleware).channel
491
508
  : persistingChannel;
492
- // Tool results carrying the __credentialRequired marker must never reach
493
- // the client or persisted history: the run suspends with credential-request
494
- // events instead (mirroring approvals), and leaving the tool call
495
- // unresulted is what lets the client resume it after connecting.
496
509
  const credentialFilteredChannel = {
497
510
  ...wrappedChannel,
511
+ // Returns what the inner send returns. Middleware runs asynchronously, so
512
+ // swallowing the promise here makes every `await channel.send(...)` upstream
513
+ // a no-op — including the one that waits for a buffering hook to flush
514
+ // before the channel closes.
498
515
  send: (event) => {
499
516
  if (event.type === 'tool-result' &&
500
517
  event.result !== null &&
@@ -502,14 +519,10 @@ export async function streamAIAgent(agentName, input, channel, params, agentSess
502
519
  '__credentialRequired' in event.result) {
503
520
  return;
504
521
  }
505
- wrappedChannel.send(event);
522
+ return wrappedChannel.send(event);
506
523
  },
507
524
  };
508
- // In delegate mode (default), suppress parent's text from reaching the client
509
- // AFTER a sub-agent has been called. If the parent responds directly (no delegation),
510
- // its text goes through normally. Sub-agent text bypasses this path entirely
511
- // (goes through subChannel → channel directly).
512
- const isDelegateMode = agent.agentMode !== 'supervise' && meta.agents?.length;
525
+ const isDelegateMode = agent.agentMode !== 'supervise' && meta?.agents?.length;
513
526
  const delegateState = { delegated: false };
514
527
  if (isDelegateMode) {
515
528
  streamContext.delegateState = delegateState;
@@ -521,7 +534,7 @@ export async function streamAIAgent(agentName, input, channel, params, agentSess
521
534
  if (delegateState.delegated &&
522
535
  (event.type === 'text-delta' || event.type === 'reasoning-delta'))
523
536
  return;
524
- credentialFilteredChannel.send(event);
537
+ return credentialFilteredChannel.send(event);
525
538
  },
526
539
  delegateState,
527
540
  }
@@ -535,7 +548,6 @@ export async function streamAIAgent(agentName, input, channel, params, agentSess
535
548
  streamChannel: outputChannel,
536
549
  persistingChannel,
537
550
  channel,
538
- runId,
539
551
  aiMiddlewares,
540
552
  });
541
553
  if (loopResult.outcome === 'approval') {
@@ -547,11 +559,38 @@ export async function streamAIAgent(agentName, input, channel, params, agentSess
547
559
  return persistingChannel.fullText;
548
560
  }
549
561
  await postStreamCleanup(persistingChannel, aiMiddlewares, singletonServices, runnerParams.messages, aiRunState, runId);
550
- channel.send({ type: 'done' });
562
+ // Through the middleware rather than straight at the channel, and awaited.
563
+ // `done` is the only signal a stream hook gets that the reply is over, and
564
+ // the ones that buffer need it: `voiceOutput` speaks a trailing fragment
565
+ // that never reached a full stop, and waits for audio it has already paid
566
+ // to synthesize. Sent raw, that work is discarded by the `close()` below.
567
+ await outputChannel.send({ type: 'done' });
551
568
  channel.close();
552
569
  return persistingChannel.fullText;
553
570
  }
554
571
  catch (err) {
572
+ // An interrupt is not a failure: the truncated text is real output the user
573
+ // already heard part of, so it is persisted and marked rather than dropped.
574
+ const interruption = interruptHandle.interruption;
575
+ if (interruption || isAbortError(err)) {
576
+ await persistingChannel.flush({ interrupted: true });
577
+ await aiRunState.updateRun(runId, { status: 'interrupted' });
578
+ // Deliberately not awaited. A tool still running must not hold the stream
579
+ // open — the whole point of barge-in is that the agent stops now — so the
580
+ // note lands later and the next run on this thread waits for it instead.
581
+ if (storage) {
582
+ trackInterruptNote(threadId, persistOrphanedToolResults(interruptHandle, storage, threadId));
583
+ }
584
+ channel.send({
585
+ type: 'interrupted',
586
+ runId,
587
+ text: persistingChannel.fullText,
588
+ reason: interruption?.reason ?? 'user',
589
+ });
590
+ channel.send({ type: 'done' });
591
+ channel.close();
592
+ return persistingChannel.fullText;
593
+ }
555
594
  for (const mw of aiMiddlewares) {
556
595
  if (mw.onError) {
557
596
  try {
@@ -561,9 +600,7 @@ export async function streamAIAgent(agentName, input, channel, params, agentSess
561
600
  messages: runnerParams.messages,
562
601
  });
563
602
  }
564
- catch {
565
- // onError hooks must not affect error flow
566
- }
603
+ catch { }
567
604
  }
568
605
  }
569
606
  await aiRunState.updateRun(runId, {
@@ -578,6 +615,54 @@ export async function streamAIAgent(agentName, input, channel, params, agentSess
578
615
  channel.close();
579
616
  return persistingChannel.fullText;
580
617
  }
618
+ finally {
619
+ interruptHandle.release();
620
+ }
621
+ }
622
+ /**
623
+ * Stop an in-flight run on behalf of a caller, after checking the run is theirs.
624
+ *
625
+ * Unlike {@link resumeAIAgent} this needs no channel: it does not continue the
626
+ * stream, it ends one. The `interrupted` event and the truncated message are
627
+ * emitted by the original {@link streamAIAgent} call on its own channel, so this
628
+ * can be reached over a plain RPC while the stream is held open elsewhere —
629
+ * which is exactly the shape a voice barge-in needs.
630
+ *
631
+ * Ownership is the whole gate, deliberately without {@link assertAgentAuthorized}.
632
+ * Resuming re-enters the agent and approves a tool call, so a revoked grant must
633
+ * block it; stopping is the opposite — if a caller's access to an agent was
634
+ * revoked mid-run, being able to stop their own run is harmless and arguably
635
+ * what you want.
636
+ *
637
+ * Returns `false` when there was nothing to stop. Racing a run that finishes on
638
+ * its own is the normal case in voice, so it is not an error.
639
+ */
640
+ export async function interruptAIAgent(input, params) {
641
+ const { aiRunState, logger } = getSingletonServices();
642
+ if (!aiRunState) {
643
+ throw new Error('AIRunStateService not available in singletonServices');
644
+ }
645
+ const run = await aiRunState.getRun(input.runId);
646
+ if (!run) {
647
+ throw new Error(`No run found for runId ${input.runId}`);
648
+ }
649
+ assertResourceOwner(resolveOwnerResourceId(params, agentSessionScope(run.agentName), run.resourceId), run.resourceId, 'run');
650
+ const stopped = signalRunInterrupt(input.runId, {
651
+ reason: input.reason ?? 'user',
652
+ });
653
+ // A run still marked `running` that this process cannot abort is executing on
654
+ // another instance. Returning a bare `false` there is indistinguishable from
655
+ // "it already finished", so the one deployment shape this registry does not
656
+ // cover fails silently — an agent that simply refuses to shut up, with nothing
657
+ // in the logs. Say so instead. See `signalRunInterrupt` for the fix (fan the
658
+ // interrupt out over eventHub so every instance tries locally).
659
+ if (!stopped && run.status === 'running') {
660
+ logger?.warn(`Could not interrupt run ${input.runId}: it is running in another process. ` +
661
+ 'Interrupts are process-local; fan them out over eventHub to support multiple instances.');
662
+ }
663
+ // Reported after the abort so it names what is *still* running: aborting the
664
+ // model call does nothing to a tool already executing.
665
+ return { stopped, inFlightTools: getInFlightTools(input.runId) };
581
666
  }
582
667
  export async function resumeAIAgent(input, channel, params, options) {
583
668
  const singletonServices = getSingletonServices();
@@ -589,16 +674,12 @@ export async function resumeAIAgent(input, channel, params, options) {
589
674
  if (!run) {
590
675
  throw new Error(`No run found for runId ${input.runId}`);
591
676
  }
592
- assertResourceOwner(resolveOwnerResourceId(params, agentSessionScope(run.agentName), run.resourceId), run.resourceId, 'run');
677
+ assertResourcePrincipalOwner(params, agentSessionScope(run.agentName), run.resourceId, 'run');
593
678
  const pending = run.pendingApprovals?.find((p) => p.toolCallId === input.toolCallId);
594
679
  if (!pending) {
595
680
  throw new Error(`No pending approval for toolCallId ${input.toolCallId} on run ${input.runId}`);
596
681
  }
597
682
  const { agent, packageName, resolvedName } = resolveAgent(run.agentName);
598
- // Gate before resolving the approval: recording it is a persisted side
599
- // effect, so an unauthorized caller must not reach it. Run ownership alone is
600
- // not enough — a grant revoked while the run was suspended must stop the
601
- // caller from approving its pending tool calls.
602
683
  await assertAgentAuthorized(agent, params, packageName);
603
684
  await aiRunState.resolveApproval(input.toolCallId, input.approved ? 'approved' : 'denied');
604
685
  const { storage } = resolveMemoryServices(agent, singletonServices);
@@ -639,11 +720,9 @@ export async function resumeAIAgent(input, channel, params, options) {
639
720
  : pending.agentName,
640
721
  result: denialResult,
641
722
  });
642
- // Check remaining pending approvals
643
723
  const updatedRun = await aiRunState.getRun(run.runId);
644
724
  const remaining = updatedRun?.pendingApprovals ?? [];
645
725
  if (remaining.length > 0) {
646
- // Still waiting for more approvals - don't continue step loop
647
726
  channel.send({ type: 'done' });
648
727
  channel.close();
649
728
  return;
@@ -748,11 +827,9 @@ export async function resumeAIAgent(input, channel, params, options) {
748
827
  ...(isError ? { isError: true } : {}),
749
828
  });
750
829
  }
751
- // Check remaining pending approvals after processing this one
752
830
  const updatedRun = await aiRunState.getRun(run.runId);
753
831
  const remaining = updatedRun?.pendingApprovals ?? [];
754
832
  if (remaining.length > 0) {
755
- // Still waiting for more approvals - don't continue step loop
756
833
  channel.send({ type: 'done' });
757
834
  channel.close();
758
835
  return;
@@ -786,6 +863,8 @@ async function continueAfterToolResult(run, agent, packageName, resolvedName, st
786
863
  }),
787
864
  ...(agent.aiMiddleware ?? []),
788
865
  ];
866
+ // One bag per run, shared by every middleware — see PikkuAIMiddlewareHooks.
867
+ const sharedNotes = {};
789
868
  let modifiedMessages = trimmedMessages;
790
869
  let modifiedInstructions = instructions;
791
870
  for (const mw of aiMiddlewares) {
@@ -793,11 +872,17 @@ async function continueAfterToolResult(run, agent, packageName, resolvedName, st
793
872
  const result = await mw.modifyInput(singletonServices, {
794
873
  messages: modifiedMessages,
795
874
  instructions: modifiedInstructions,
875
+ shared: sharedNotes,
796
876
  });
797
877
  modifiedMessages = result.messages;
798
878
  modifiedInstructions = result.instructions;
799
879
  }
800
880
  }
881
+ // Resuming is as interruptible as the first turn. It is the same person
882
+ // listening to the same voice, and after an approval it is where most of the
883
+ // reply actually gets spoken — an approved delete is followed by the agent
884
+ // talking about it, and that is a normal thing to talk over.
885
+ const interruptHandle = registerInterruptibleRun(run.runId);
801
886
  const streamMiddleware = aiMiddlewares
802
887
  .filter((mw) => mw.modifyOutputStream)
803
888
  .map((mw) => {
@@ -809,6 +894,11 @@ async function continueAfterToolResult(run, agent, packageName, resolvedName, st
809
894
  event,
810
895
  allEvents,
811
896
  state,
897
+ shared: sharedNotes,
898
+ // Sends downstream directly, so a hook can hand back the fast event
899
+ // now and push the slow one when it is ready.
900
+ emit: next,
901
+ signal: interruptHandle.signal,
812
902
  });
813
903
  if (result == null)
814
904
  return;
@@ -844,10 +934,13 @@ async function continueAfterToolResult(run, agent, packageName, resolvedName, st
844
934
  tools: resumeTools,
845
935
  maxSteps: 1,
846
936
  toolChoice: (agent.toolChoice ?? 'auto'),
937
+ providerOptions: agent.providerOptions,
847
938
  outputSchema: meta?.outputSchema
848
939
  ? pikkuState(packageName, 'misc', 'schemas').get(meta.outputSchema)
849
940
  : undefined,
850
941
  };
942
+ runnerParams.abortSignal = interruptHandle.signal;
943
+ runnerParams.tools = trackToolExecution(runnerParams.tools, interruptHandle);
851
944
  try {
852
945
  const loopResult = await runStreamStepLoop({
853
946
  agent,
@@ -857,7 +950,6 @@ async function continueAfterToolResult(run, agent, packageName, resolvedName, st
857
950
  streamChannel: wrappedChannel,
858
951
  persistingChannel,
859
952
  channel,
860
- runId: run.runId,
861
953
  aiMiddlewares,
862
954
  });
863
955
  if (loopResult.outcome === 'approval') {
@@ -869,10 +961,33 @@ async function continueAfterToolResult(run, agent, packageName, resolvedName, st
869
961
  return;
870
962
  }
871
963
  await postStreamCleanup(persistingChannel, aiMiddlewares, singletonServices, runnerParams.messages, aiRunState, run.runId);
872
- channel.send({ type: 'done' });
964
+ // Through the middleware, for the same reason as the first turn — and it
965
+ // matters more here. After an approval, most of what gets spoken is the
966
+ // agent talking about what it just did, so this is the half of the reply a
967
+ // dropped flush would silence.
968
+ await wrappedChannel.send({ type: 'done' });
873
969
  channel.close();
874
970
  }
875
971
  catch (err) {
972
+ // Same reasoning as the first turn: an interrupt is not a failure, and the
973
+ // part of the reply the user already heard is real output.
974
+ const interruption = interruptHandle.interruption;
975
+ if (interruption || isAbortError(err)) {
976
+ await persistingChannel.flush({ interrupted: true });
977
+ await aiRunState.updateRun(run.runId, { status: 'interrupted' });
978
+ if (storage) {
979
+ trackInterruptNote(run.threadId, persistOrphanedToolResults(interruptHandle, storage, run.threadId));
980
+ }
981
+ channel.send({
982
+ type: 'interrupted',
983
+ runId: run.runId,
984
+ text: persistingChannel.fullText,
985
+ reason: interruption?.reason ?? 'user',
986
+ });
987
+ channel.send({ type: 'done' });
988
+ channel.close();
989
+ return;
990
+ }
876
991
  for (const mw of aiMiddlewares) {
877
992
  if (mw.onError) {
878
993
  try {
@@ -882,9 +997,7 @@ async function continueAfterToolResult(run, agent, packageName, resolvedName, st
882
997
  messages: runnerParams.messages,
883
998
  });
884
999
  }
885
- catch {
886
- // onError hooks must not affect error flow
887
- }
1000
+ catch { }
888
1001
  }
889
1002
  }
890
1003
  await aiRunState.updateRun(run.runId, {
@@ -898,4 +1011,7 @@ async function continueAfterToolResult(run, agent, packageName, resolvedName, st
898
1011
  channel.send({ type: 'done' });
899
1012
  channel.close();
900
1013
  }
1014
+ finally {
1015
+ interruptHandle.release();
1016
+ }
901
1017
  }