@pikku/core 0.12.72 → 0.12.74

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 (811) hide show
  1. package/CHANGELOG.md +793 -0
  2. package/dist/crypto-utils.d.ts +30 -5
  3. package/dist/crypto-utils.js +146 -41
  4. package/dist/dev/hot-reload.js +11 -30
  5. package/dist/dev/module-runner.d.ts +3 -7
  6. package/dist/dev/module-runner.js +4 -10
  7. package/dist/dev/reload-meta.d.ts +8 -20
  8. package/dist/dev/reload-meta.js +9 -29
  9. package/dist/errors/error-handler.d.ts +5 -30
  10. package/dist/errors/error-handler.js +16 -32
  11. package/dist/errors/errors.d.ts +32 -151
  12. package/dist/errors/errors.js +55 -157
  13. package/dist/function/abort-scope.d.ts +47 -0
  14. package/dist/function/abort-scope.js +63 -0
  15. package/dist/function/function-runner.js +37 -32
  16. package/dist/function/functions.types.d.ts +44 -136
  17. package/dist/function/functions.types.js +0 -58
  18. package/dist/function/list.types.d.ts +12 -62
  19. package/dist/function/list.types.js +4 -25
  20. package/dist/handle-error.d.ts +0 -13
  21. package/dist/handle-error.js +0 -18
  22. package/dist/index.d.ts +5 -2
  23. package/dist/index.js +4 -1
  24. package/dist/middleware/auth-apikey.d.ts +3 -18
  25. package/dist/middleware/auth-apikey.js +0 -17
  26. package/dist/middleware/auth-bearer.d.ts +6 -41
  27. package/dist/middleware/auth-bearer.js +3 -40
  28. package/dist/middleware/auth-cookie.d.ts +5 -27
  29. package/dist/middleware/auth-cookie.js +2 -26
  30. package/dist/middleware/cors.d.ts +7 -34
  31. package/dist/middleware/cors.js +7 -34
  32. package/dist/middleware/remote-auth.d.ts +3 -1
  33. package/dist/middleware/remote-auth.js +3 -2
  34. package/dist/middleware/telemetry.d.ts +8 -33
  35. package/dist/middleware/telemetry.js +2 -31
  36. package/dist/middleware-runner.d.ts +4 -55
  37. package/dist/middleware-runner.js +5 -74
  38. package/dist/permissions.d.ts +3 -44
  39. package/dist/permissions.js +19 -71
  40. package/dist/pikku-request.d.ts +0 -6
  41. package/dist/pikku-request.js +0 -6
  42. package/dist/pikku-state.d.ts +0 -26
  43. package/dist/pikku-state.js +2 -30
  44. package/dist/remote.d.ts +3 -5
  45. package/dist/remote.js +8 -7
  46. package/dist/schema.d.ts +5 -39
  47. package/dist/schema.js +5 -39
  48. package/dist/scopes.d.ts +4 -23
  49. package/dist/scopes.js +7 -48
  50. package/dist/services/ai-agent-runner-service.d.ts +20 -0
  51. package/dist/services/ai-embedding-service.d.ts +2 -25
  52. package/dist/services/audit-service.js +1 -2
  53. package/dist/services/content-service.d.ts +1 -46
  54. package/dist/services/credential-service.d.ts +3 -40
  55. package/dist/services/deployment-service.d.ts +3 -9
  56. package/dist/services/gateway-service.d.ts +0 -15
  57. package/dist/services/http-personas.d.ts +80 -0
  58. package/dist/services/http-personas.js +233 -0
  59. package/dist/services/in-memory-queue-service.d.ts +0 -14
  60. package/dist/services/in-memory-queue-service.js +1 -15
  61. package/dist/services/in-memory-trigger-service.d.ts +0 -18
  62. package/dist/services/in-memory-trigger-service.js +1 -18
  63. package/dist/services/in-memory-workflow-service.d.ts +0 -16
  64. package/dist/services/in-memory-workflow-service.js +4 -33
  65. package/dist/services/index.d.ts +5 -6
  66. package/dist/services/index.js +2 -5
  67. package/dist/services/istanbul-coverage-service.d.ts +1 -5
  68. package/dist/services/istanbul-coverage-service.js +2 -8
  69. package/dist/services/jwt-service.d.ts +1 -16
  70. package/dist/services/local-content.d.ts +13 -2
  71. package/dist/services/local-content.js +40 -13
  72. package/dist/services/local-gateway-service.d.ts +0 -16
  73. package/dist/services/local-gateway-service.js +2 -17
  74. package/dist/services/local-secrets.d.ts +0 -4
  75. package/dist/services/local-secrets.js +0 -4
  76. package/dist/services/logger-console.d.ts +3 -7
  77. package/dist/services/logger-console.js +3 -7
  78. package/dist/services/logger.d.ts +2 -37
  79. package/dist/services/meta-service.d.ts +23 -26
  80. package/dist/services/meta-service.js +22 -36
  81. package/dist/services/personas-service.d.ts +134 -0
  82. package/dist/services/personas-service.js +40 -0
  83. package/dist/services/pikku-user-id.js +0 -4
  84. package/dist/services/queue-webhook-service.d.ts +2 -36
  85. package/dist/services/queue-webhook-service.js +9 -41
  86. package/dist/services/scheduler-service.d.ts +1 -50
  87. package/dist/services/scheduler-service.js +0 -10
  88. package/dist/services/schema-service.d.ts +1 -24
  89. package/dist/services/scope-service.d.ts +49 -34
  90. package/dist/services/scoped-secret-service.d.ts +0 -4
  91. package/dist/services/scoped-secret-service.js +0 -4
  92. package/dist/services/secret-host-binding.d.ts +8 -0
  93. package/dist/services/secret-host-binding.js +36 -0
  94. package/dist/services/secret-service.d.ts +5 -33
  95. package/dist/services/secretless.d.ts +6 -0
  96. package/dist/services/secretless.js +21 -0
  97. package/dist/services/stub-tracker.d.ts +7 -18
  98. package/dist/services/stub-tracker.js +8 -18
  99. package/dist/services/system-role-guard.d.ts +33 -0
  100. package/dist/services/system-role-guard.js +38 -0
  101. package/dist/services/trigger-service.d.ts +0 -12
  102. package/dist/services/typed-secret-service.d.ts +0 -7
  103. package/dist/services/typed-secret-service.js +1 -7
  104. package/dist/services/v8-coverage-service.d.ts +2 -3
  105. package/dist/services/v8-coverage-service.js +1 -2
  106. package/dist/services/variables-service.d.ts +1 -8
  107. package/dist/services/webhook-service.d.ts +19 -63
  108. package/dist/services/webhook-service.js +6 -20
  109. package/dist/services/workflow-service.d.ts +3 -15
  110. package/dist/testing/service-tests.js +0 -17
  111. package/dist/time-utils.d.ts +0 -16
  112. package/dist/time-utils.js +1 -19
  113. package/dist/types/core.types.d.ts +99 -219
  114. package/dist/types/core.types.js +0 -42
  115. package/dist/types/state.types.d.ts +4 -9
  116. package/dist/utils/hmac.d.ts +4 -10
  117. package/dist/utils/hmac.js +4 -10
  118. package/dist/utils/safe-fetch.d.ts +7 -35
  119. package/dist/utils/safe-fetch.js +13 -53
  120. package/dist/utils.d.ts +1 -6
  121. package/dist/utils.js +6 -15
  122. package/dist/wirings/actor-flow/actor-flow.types.d.ts +1 -34
  123. package/dist/wirings/actor-flow/index.d.ts +0 -9
  124. package/dist/wirings/actor-flow/run-conversation.d.ts +5 -5
  125. package/dist/wirings/actor-flow/run-conversation.js +14 -7
  126. package/dist/wirings/ai-agent/ai-agent-agui.d.ts +0 -5
  127. package/dist/wirings/ai-agent/ai-agent-agui.js +34 -12
  128. package/dist/wirings/ai-agent/ai-agent-helpers.d.ts +7 -0
  129. package/dist/wirings/ai-agent/ai-agent-helpers.js +7 -0
  130. package/dist/wirings/ai-agent/ai-agent-interrupt.d.ts +153 -0
  131. package/dist/wirings/ai-agent/ai-agent-interrupt.js +256 -0
  132. package/dist/wirings/ai-agent/ai-agent-memory.js +0 -2
  133. package/dist/wirings/ai-agent/ai-agent-model-config.d.ts +0 -9
  134. package/dist/wirings/ai-agent/ai-agent-model-config.js +1 -9
  135. package/dist/wirings/ai-agent/ai-agent-prepare.d.ts +10 -99
  136. package/dist/wirings/ai-agent/ai-agent-prepare.js +58 -131
  137. package/dist/wirings/ai-agent/ai-agent-registry.d.ts +2 -1
  138. package/dist/wirings/ai-agent/ai-agent-registry.js +5 -1
  139. package/dist/wirings/ai-agent/ai-agent-runner.js +49 -20
  140. package/dist/wirings/ai-agent/ai-agent-stream.d.ts +25 -2
  141. package/dist/wirings/ai-agent/ai-agent-stream.js +153 -63
  142. package/dist/wirings/ai-agent/ai-agent.types.d.ts +84 -4
  143. package/dist/wirings/ai-agent/index.d.ts +6 -4
  144. package/dist/wirings/ai-agent/index.js +5 -4
  145. package/dist/wirings/ai-agent/voice-input.d.ts +39 -1
  146. package/dist/wirings/ai-agent/voice-input.js +46 -3
  147. package/dist/wirings/ai-agent/voice-output.d.ts +54 -1
  148. package/dist/wirings/ai-agent/voice-output.js +153 -50
  149. package/dist/wirings/channel/channel-common.d.ts +7 -20
  150. package/dist/wirings/channel/channel-common.js +7 -21
  151. package/dist/wirings/channel/channel-handler.js +25 -6
  152. package/dist/wirings/channel/channel-host-rpc.d.ts +25 -0
  153. package/dist/wirings/channel/channel-host-rpc.js +38 -0
  154. package/dist/wirings/channel/channel-middleware-runner.d.ts +0 -12
  155. package/dist/wirings/channel/channel-middleware-runner.js +0 -12
  156. package/dist/wirings/channel/channel-rpc-registry.d.ts +31 -0
  157. package/dist/wirings/channel/channel-rpc-registry.js +89 -0
  158. package/dist/wirings/channel/channel-rpc-responder.d.ts +15 -0
  159. package/dist/wirings/channel/channel-rpc-responder.js +71 -0
  160. package/dist/wirings/channel/channel-rpc-service.d.ts +40 -0
  161. package/dist/wirings/channel/channel-rpc-service.js +106 -0
  162. package/dist/wirings/channel/channel-rpc-validators.d.ts +14 -0
  163. package/dist/wirings/channel/channel-rpc-validators.js +30 -0
  164. package/dist/wirings/channel/channel-rpc.d.ts +5 -0
  165. package/dist/wirings/channel/channel-rpc.js +5 -0
  166. package/dist/wirings/channel/channel-rpc.types.d.ts +90 -0
  167. package/dist/wirings/channel/channel-rpc.types.js +50 -0
  168. package/dist/wirings/channel/channel-runner.d.ts +0 -4
  169. package/dist/wirings/channel/channel-runner.js +0 -14
  170. package/dist/wirings/channel/channel-store.d.ts +0 -10
  171. package/dist/wirings/channel/channel.types.d.ts +12 -1
  172. package/dist/wirings/channel/define-channel-routes.d.ts +0 -20
  173. package/dist/wirings/channel/define-channel-routes.js +0 -20
  174. package/dist/wirings/channel/eventhub-service.d.ts +0 -18
  175. package/dist/wirings/channel/index.d.ts +4 -1
  176. package/dist/wirings/channel/index.js +2 -0
  177. package/dist/wirings/channel/local/local-channel-runner.js +3 -1
  178. package/dist/wirings/channel/local/local-eventhub-service.d.ts +0 -33
  179. package/dist/wirings/channel/local/local-eventhub-service.js +2 -36
  180. package/dist/wirings/channel/log-channels.d.ts +0 -4
  181. package/dist/wirings/channel/log-channels.js +0 -4
  182. package/dist/wirings/channel/pikku-abstract-channel-handler.js +6 -0
  183. package/dist/wirings/channel/serverless/serverless-channel-runner.js +2 -5
  184. package/dist/wirings/cli/channel/cli-approval.d.ts +41 -0
  185. package/dist/wirings/cli/channel/cli-approval.js +81 -0
  186. package/dist/wirings/cli/channel/cli-channel-runner.d.ts +0 -4
  187. package/dist/wirings/cli/channel/cli-channel-runner.js +3 -25
  188. package/dist/wirings/cli/channel/cli-raw-channel-runner.d.ts +47 -9
  189. package/dist/wirings/cli/channel/cli-raw-channel-runner.js +24 -16
  190. package/dist/wirings/cli/channel/cli-raw-client-runner.d.ts +20 -0
  191. package/dist/wirings/cli/channel/cli-raw-client-runner.js +121 -0
  192. package/dist/wirings/cli/channel/index.d.ts +4 -0
  193. package/dist/wirings/cli/channel/index.js +2 -0
  194. package/dist/wirings/cli/cli-runner.d.ts +20 -20
  195. package/dist/wirings/cli/cli-runner.js +28 -89
  196. package/dist/wirings/cli/cli.types.d.ts +14 -3
  197. package/dist/wirings/cli/command-parser.d.ts +1 -10
  198. package/dist/wirings/cli/command-parser.js +10 -87
  199. package/dist/wirings/cli/define-cli-commands.d.ts +1 -17
  200. package/dist/wirings/cli/define-cli-commands.js +1 -17
  201. package/dist/wirings/credential/credential.types.d.ts +0 -12
  202. package/dist/wirings/credential/define-credential.d.ts +48 -0
  203. package/dist/wirings/credential/define-credential.js +47 -0
  204. package/dist/wirings/credential/index.d.ts +1 -1
  205. package/dist/wirings/credential/index.js +1 -1
  206. package/dist/wirings/credential/validate-credential-definitions.d.ts +2 -4
  207. package/dist/wirings/gateway/gateway-runner.d.ts +1 -20
  208. package/dist/wirings/gateway/gateway-runner.js +8 -105
  209. package/dist/wirings/gateway/gateway.types.d.ts +7 -80
  210. package/dist/wirings/http/http-routes.d.ts +0 -63
  211. package/dist/wirings/http/http-routes.js +0 -63
  212. package/dist/wirings/http/http-runner.d.ts +0 -99
  213. package/dist/wirings/http/http-runner.js +9 -165
  214. package/dist/wirings/http/http.types.d.ts +14 -55
  215. package/dist/wirings/http/log-http-routes.d.ts +0 -4
  216. package/dist/wirings/http/log-http-routes.js +0 -4
  217. package/dist/wirings/http/pikku-fetch-http-request.d.ts +0 -40
  218. package/dist/wirings/http/pikku-fetch-http-request.js +0 -58
  219. package/dist/wirings/http/pikku-fetch-http-response.js +0 -3
  220. package/dist/wirings/http/routers/path-to-regex.js +2 -13
  221. package/dist/wirings/http/web-request.d.ts +0 -8
  222. package/dist/wirings/http/web-request.js +25 -17
  223. package/dist/wirings/mcp/mcp-runner.d.ts +1 -4
  224. package/dist/wirings/mcp/mcp-runner.js +1 -14
  225. package/dist/wirings/mcp/mcp.types.d.ts +2 -35
  226. package/dist/wirings/oauth2/oauth2.types.d.ts +0 -28
  227. package/dist/wirings/oauth2/oauth2.types.js +0 -3
  228. package/dist/wirings/persona/define-personas.d.ts +28 -0
  229. package/dist/wirings/persona/define-personas.js +27 -0
  230. package/dist/wirings/persona/index.d.ts +21 -0
  231. package/dist/wirings/persona/index.js +17 -0
  232. package/dist/wirings/persona/persona-email.d.ts +37 -0
  233. package/dist/wirings/persona/persona-email.js +69 -0
  234. package/dist/wirings/persona/persona-environments.d.ts +45 -0
  235. package/dist/wirings/persona/persona-environments.js +81 -0
  236. package/dist/wirings/persona/persona-mailbox.d.ts +101 -0
  237. package/dist/wirings/persona/persona-mailbox.js +53 -0
  238. package/dist/wirings/persona/persona.types.d.ts +125 -0
  239. package/dist/wirings/persona/persona.types.js +1 -0
  240. package/dist/wirings/persona/validate-personas.d.ts +53 -0
  241. package/dist/wirings/persona/validate-personas.js +94 -0
  242. package/dist/wirings/queue/index.d.ts +3 -0
  243. package/dist/wirings/queue/index.js +2 -3
  244. package/dist/wirings/queue/queue-identity.d.ts +28 -0
  245. package/dist/wirings/queue/queue-identity.js +102 -0
  246. package/dist/wirings/queue/queue-runner.d.ts +0 -19
  247. package/dist/wirings/queue/queue-runner.js +9 -30
  248. package/dist/wirings/queue/queue.types.d.ts +18 -89
  249. package/dist/wirings/queue/register-queue-helper.d.ts +0 -12
  250. package/dist/wirings/queue/register-queue-helper.js +0 -11
  251. package/dist/wirings/queue/signed-queue-service.d.ts +16 -0
  252. package/dist/wirings/queue/signed-queue-service.js +42 -0
  253. package/dist/wirings/queue/validate-worker-config.d.ts +2 -23
  254. package/dist/wirings/queue/validate-worker-config.js +0 -14
  255. package/dist/wirings/role/define-system-role.d.ts +32 -0
  256. package/dist/wirings/role/define-system-role.js +31 -0
  257. package/dist/wirings/role/index.d.ts +3 -0
  258. package/dist/wirings/role/index.js +2 -0
  259. package/dist/wirings/role/role.types.d.ts +43 -0
  260. package/dist/wirings/role/role.types.js +1 -0
  261. package/dist/wirings/role/validate-role-definitions.d.ts +21 -0
  262. package/dist/wirings/role/validate-role-definitions.js +71 -0
  263. package/dist/wirings/rpc/addon-runner.d.ts +0 -19
  264. package/dist/wirings/rpc/addon-runner.js +0 -51
  265. package/dist/wirings/rpc/remote-addon-auth.d.ts +1 -12
  266. package/dist/wirings/rpc/remote-addon-auth.js +1 -9
  267. package/dist/wirings/rpc/rpc-runner.d.ts +11 -18
  268. package/dist/wirings/rpc/rpc-runner.js +88 -105
  269. package/dist/wirings/rpc/rpc-types.d.ts +7 -6
  270. package/dist/wirings/rpc/wire-addon.d.ts +25 -0
  271. package/dist/wirings/rpc/wire-addon.js +62 -0
  272. package/dist/wirings/rpc/wire-remote-addon.d.ts +3 -28
  273. package/dist/wirings/rpc/wire-remote-addon.js +0 -8
  274. package/dist/wirings/scheduler/log-schedulers.d.ts +0 -4
  275. package/dist/wirings/scheduler/log-schedulers.js +0 -4
  276. package/dist/wirings/scheduler/scheduler-runner.d.ts +0 -1
  277. package/dist/wirings/scheduler/scheduler-runner.js +0 -1
  278. package/dist/wirings/scheduler/scheduler.types.d.ts +1 -14
  279. package/dist/wirings/scope/define-scope.d.ts +32 -0
  280. package/dist/wirings/scope/define-scope.js +31 -0
  281. package/dist/wirings/scope/index.d.ts +1 -1
  282. package/dist/wirings/scope/index.js +1 -1
  283. package/dist/wirings/scope/scope.types.d.ts +7 -9
  284. package/dist/wirings/scope/validate-scope-definitions.d.ts +2 -21
  285. package/dist/wirings/scope/validate-scope-definitions.js +3 -21
  286. package/dist/wirings/secret/index.d.ts +1 -1
  287. package/dist/wirings/secret/index.js +1 -1
  288. package/dist/wirings/secret/secret.types.d.ts +19 -15
  289. package/dist/wirings/secret/secret.types.js +1 -1
  290. package/dist/wirings/secret/validate-secret-definitions.d.ts +2 -4
  291. package/dist/wirings/trigger/trigger-runner.d.ts +0 -27
  292. package/dist/wirings/trigger/trigger-runner.js +1 -24
  293. package/dist/wirings/trigger/trigger.types.d.ts +1 -82
  294. package/dist/wirings/trigger/trigger.types.js +0 -34
  295. package/dist/wirings/variable/index.d.ts +1 -1
  296. package/dist/wirings/variable/index.js +1 -1
  297. package/dist/wirings/variable/validate-variable-definitions.d.ts +2 -4
  298. package/dist/wirings/variable/variable.types.d.ts +1 -13
  299. package/dist/wirings/variable/variable.types.js +1 -1
  300. package/dist/wirings/virtual-user/index.d.ts +27 -0
  301. package/dist/wirings/virtual-user/index.js +8 -0
  302. package/dist/wirings/virtual-user/run-virtual-user.d.ts +92 -0
  303. package/dist/wirings/virtual-user/run-virtual-user.js +478 -0
  304. package/dist/wirings/virtual-user/virtual-user-agents.d.ts +38 -0
  305. package/dist/wirings/virtual-user/virtual-user-agents.js +24 -0
  306. package/dist/wirings/virtual-user/virtual-user-catalogue.d.ts +92 -0
  307. package/dist/wirings/virtual-user/virtual-user-catalogue.js +134 -0
  308. package/dist/wirings/virtual-user/virtual-user-derive.d.ts +26 -0
  309. package/dist/wirings/virtual-user/virtual-user-derive.js +137 -0
  310. package/dist/wirings/virtual-user/virtual-user-dispositions.d.ts +79 -0
  311. package/dist/wirings/virtual-user/virtual-user-dispositions.js +128 -0
  312. package/dist/wirings/virtual-user/virtual-user-intents.d.ts +78 -0
  313. package/dist/wirings/virtual-user/virtual-user-intents.js +142 -0
  314. package/dist/wirings/virtual-user/virtual-user-rng.d.ts +24 -0
  315. package/dist/wirings/virtual-user/virtual-user-rng.js +44 -0
  316. package/dist/wirings/virtual-user/virtual-user-target.d.ts +21 -0
  317. package/dist/wirings/virtual-user/virtual-user-target.js +34 -0
  318. package/dist/wirings/virtual-user/virtual-user.types.d.ts +199 -0
  319. package/dist/wirings/virtual-user/virtual-user.types.js +8 -0
  320. package/dist/wirings/workflow/dsl/workflow-dsl.types.d.ts +5 -5
  321. package/dist/wirings/workflow/dsl/workflow-runner.d.ts +0 -4
  322. package/dist/wirings/workflow/dsl/workflow-runner.js +0 -4
  323. package/dist/wirings/workflow/feature.d.ts +0 -19
  324. package/dist/wirings/workflow/feature.js +0 -19
  325. package/dist/wirings/workflow/graph/graph-node.d.ts +0 -98
  326. package/dist/wirings/workflow/graph/graph-node.js +0 -34
  327. package/dist/wirings/workflow/graph/graph-runner.js +6 -41
  328. package/dist/wirings/workflow/graph/wire-workflow-graph.d.ts +0 -4
  329. package/dist/wirings/workflow/graph/workflow-graph.types.d.ts +0 -58
  330. package/dist/wirings/workflow/graph/workflow-graph.types.js +0 -6
  331. package/dist/wirings/workflow/index.d.ts +5 -7
  332. package/dist/wirings/workflow/index.js +3 -17
  333. package/dist/wirings/workflow/pikku-scenario-service.d.ts +87 -5
  334. package/dist/wirings/workflow/pikku-scenario-service.js +204 -42
  335. package/dist/wirings/workflow/pikku-workflow-service.d.ts +7 -459
  336. package/dist/wirings/workflow/pikku-workflow-service.js +58 -551
  337. package/dist/wirings/workflow/run-timeline.d.ts +0 -47
  338. package/dist/wirings/workflow/run-timeline.js +0 -22
  339. package/dist/wirings/workflow/scenario-cookie-jar.d.ts +0 -23
  340. package/dist/wirings/workflow/scenario-cookie-jar.js +0 -16
  341. package/dist/wirings/workflow/scenario-poll.d.ts +0 -15
  342. package/dist/wirings/workflow/scenario-poll.js +0 -12
  343. package/dist/wirings/workflow/scenario-prose.d.ts +0 -28
  344. package/dist/wirings/workflow/scenario-prose.js +0 -18
  345. package/dist/wirings/workflow/scenario-step-guards.d.ts +0 -13
  346. package/dist/wirings/workflow/scenario-step-guards.js +1 -14
  347. package/dist/wirings/workflow/scenario-step.types.d.ts +72 -6
  348. package/dist/wirings/workflow/scenario-step.types.js +5 -1
  349. package/dist/wirings/workflow/scenario-surface.d.ts +16 -0
  350. package/dist/wirings/workflow/scenario-surface.js +56 -0
  351. package/dist/wirings/workflow/workflow-invocation-id.d.ts +0 -18
  352. package/dist/wirings/workflow/workflow-invocation-id.js +2 -22
  353. package/dist/wirings/workflow/workflow-queue-workers.d.ts +0 -20
  354. package/dist/wirings/workflow/workflow-queue-workers.js +0 -19
  355. package/dist/wirings/workflow/workflow.types.d.ts +0 -197
  356. package/knowledge/decisions/index.md +19 -0
  357. package/knowledge/decisions/internals/a-secret-that-fails-to-decrypt-fails-the-whole-read.md +49 -0
  358. package/knowledge/decisions/internals/actor-flow-conversations-seed-a-hidden-kickoff-message.md +23 -0
  359. package/knowledge/decisions/internals/actor-flow-drives-the-target-through-a-transport-seam.md +24 -0
  360. package/knowledge/decisions/internals/actor-flow-verdicts-are-llm-self-evaluations.md +25 -0
  361. package/knowledge/decisions/internals/addon-package-roots-resolve-by-walking-node-module-search-paths.md +26 -0
  362. package/knowledge/decisions/internals/addon-singleton-services-are-cached-per-namespace-not-per-package.md +33 -0
  363. package/knowledge/decisions/internals/addon-workflow-names-are-prefixed-with-the-consumer-namespace.md +28 -0
  364. package/knowledge/decisions/internals/ai-agent-agui-bridge-obeys-the-client-ordering-contract.md +29 -0
  365. package/knowledge/decisions/internals/ai-agent-audio-chunks-carry-the-format-the-provider-returned.md +20 -0
  366. package/knowledge/decisions/internals/ai-agent-credential-suspensions-hide-the-tool-result.md +26 -0
  367. package/knowledge/decisions/internals/ai-agent-delegate-and-supervise-hide-different-text.md +26 -0
  368. package/knowledge/decisions/internals/ai-agent-llm-tool-arguments-have-nulls-stripped.md +23 -0
  369. package/knowledge/decisions/internals/ai-agent-model-config-stays-a-single-resolution-seam.md +25 -0
  370. package/knowledge/decisions/internals/ai-agent-onerror-hooks-cannot-change-the-failure.md +22 -0
  371. package/knowledge/decisions/internals/ai-agent-runner-methods-must-keep-their-receiver.md +22 -0
  372. package/knowledge/decisions/internals/ai-agent-stream-persistence-is-best-effort.md +27 -0
  373. package/knowledge/decisions/internals/ai-agent-sub-agents-inherit-the-parent-context-block.md +26 -0
  374. package/knowledge/decisions/internals/ai-agent-tool-execute-failures-are-logged-unconditionally.md +25 -0
  375. package/knowledge/decisions/internals/ai-agent-voice-input-transcribes-audio-parts-in-place.md +22 -0
  376. package/knowledge/decisions/internals/ai-agent-working-memory-is-persisted-only-when-valid.md +25 -0
  377. package/knowledge/decisions/internals/channel-message-handlers-accept-three-config-shapes.md +30 -0
  378. package/knowledge/decisions/internals/channel-middleware-caches-only-statically-resolved-middleware.md +31 -0
  379. package/knowledge/decisions/internals/channel-state-is-per-socket-session-state-is-per-user.md +29 -0
  380. package/knowledge/decisions/internals/channel-user-id-is-persisted-after-onconnect-middleware-runs.md +28 -0
  381. package/knowledge/decisions/internals/cli-option-names-are-camelcase-in-state-and-kebab-on-the-command-line.md +27 -0
  382. package/knowledge/decisions/internals/cli-parse-errors-are-routed-by-message-prefix.md +28 -0
  383. package/knowledge/decisions/internals/cli-stdout-is-reserved-for-machine-readable-output.md +34 -0
  384. package/knowledge/decisions/internals/cli-unknown-long-options-warn-instead-of-failing.md +29 -0
  385. package/knowledge/decisions/internals/core-data-classification-brand-is-an-optional-property.md +34 -0
  386. package/knowledge/decisions/internals/core-function-runner-restores-the-wire-fields-it-overwrites.md +44 -0
  387. package/knowledge/decisions/internals/core-hot-reload-merges-generated-meta-never-replaces-it.md +39 -0
  388. package/knowledge/decisions/internals/core-hot-reload-owns-its-module-registry.md +42 -0
  389. package/knowledge/decisions/internals/core-middleware-order-is-scope-then-priority.md +39 -0
  390. package/knowledge/decisions/internals/core-schema-defaults-apply-on-every-transport.md +43 -0
  391. package/knowledge/decisions/internals/core-scopes-are-an-and-gate-separate-from-permissions.md +38 -0
  392. package/knowledge/decisions/internals/core-state-is-a-global-map-written-only-at-registration-time.md +44 -0
  393. package/knowledge/decisions/internals/email-meta-is-read-uncached-because-codegen-rewrites-it-mid-session.md +27 -0
  394. package/knowledge/decisions/internals/gateway-adapters-resolve-lazily-and-are-promise-cached.md +32 -0
  395. package/knowledge/decisions/internals/gateway-webhook-challenges-echo-bytes-not-json.md +28 -0
  396. package/knowledge/decisions/internals/gateway-wiring-is-a-meta-wiring-over-http-and-channels.md +31 -0
  397. package/knowledge/decisions/internals/generated-src-paths-in-pikku-meta-are-absolute.md +26 -0
  398. package/knowledge/decisions/internals/http-request-bodies-are-read-once-and-shared.md +32 -0
  399. package/knowledge/decisions/internals/http-route-groups-cascade-config-in-a-fixed-order.md +28 -0
  400. package/knowledge/decisions/internals/http-router-matches-normalized-paths-but-returns-registered-ones.md +30 -0
  401. package/knowledge/decisions/internals/http-runner-logs-through-a-trace-scoped-logger-functions-do-not.md +26 -0
  402. package/knowledge/decisions/internals/http-set-cookie-headers-are-appended-never-joined.md +28 -0
  403. package/knowledge/decisions/internals/http-sse-streams-flush-headers-only-after-middleware.md +32 -0
  404. package/knowledge/decisions/internals/http-wiring-without-metadata-is-skipped-not-fatal.md +26 -0
  405. package/knowledge/decisions/internals/in-a-scenario-a-4xx-is-data-not-an-exception.md +25 -0
  406. package/knowledge/decisions/internals/in-memory-workflow-history-aliases-the-live-step-object.md +26 -0
  407. package/knowledge/decisions/internals/index.md +113 -0
  408. package/knowledge/decisions/internals/istanbul-statement-counts-attach-to-the-start-line-only.md +25 -0
  409. package/knowledge/decisions/internals/local-trigger-and-gateway-services-assume-a-single-process.md +26 -0
  410. package/knowledge/decisions/internals/node-only-builtins-are-imported-dynamically.md +24 -0
  411. package/knowledge/decisions/internals/queue-group-concurrency-keeps-one-shared-queue-fair.md +28 -0
  412. package/knowledge/decisions/internals/queue-jobs-always-carry-an-explicit-attempts-count.md +27 -0
  413. package/knowledge/decisions/internals/remote-addons-dispatch-over-http-instead-of-local-meta.md +31 -0
  414. package/knowledge/decisions/internals/rpc-names-resolve-through-package-scope-before-root.md +32 -0
  415. package/knowledge/decisions/internals/scenario-agent-calls-sign-in-on-401-only.md +27 -0
  416. package/knowledge/decisions/internals/scenario-meta-lives-apart-from-app-meta-but-merges-when-read-off-disk.md +26 -0
  417. package/knowledge/decisions/internals/scenario-steps-return-drained-response-records.md +27 -0
  418. package/knowledge/decisions/internals/scope-roots-may-be-co-declared-by-an-addon-and-its-host-app.md +30 -0
  419. package/knowledge/decisions/internals/serverless-channel-disconnect-must-tolerate-a-missing-channel.md +28 -0
  420. package/knowledge/decisions/internals/the-dev-queue-copies-prod-timing-and-serialization-semantics.md +30 -0
  421. package/knowledge/decisions/internals/the-embedding-model-is-pinned-per-service-and-doc-query-embedding-is-split.md +29 -0
  422. package/knowledge/decisions/internals/the-in-memory-workflow-service-is-inline-only-and-single-process.md +27 -0
  423. package/knowledge/decisions/internals/the-kek-salt-is-scoped-to-the-key-version.md +40 -0
  424. package/knowledge/decisions/internals/the-schema-service-is-never-stubbed.md +26 -0
  425. package/knowledge/decisions/internals/trigger-declaration-is-split-from-trigger-source.md +33 -0
  426. package/knowledge/decisions/internals/typed-secret-service-caches-for-the-process-lifetime.md +26 -0
  427. package/knowledge/decisions/internals/webhook-delivery-history-records-every-attempt-best-effort.md +26 -0
  428. package/knowledge/decisions/internals/webhook-service-collaborators-are-constructor-args-not-locator-lookups.md +25 -0
  429. package/knowledge/decisions/internals/whether-a-run-is-inline-is-read-from-the-run-record.md +58 -0
  430. package/knowledge/decisions/internals/workflow-approval-expiry-is-decided-from-a-recorded-deadline.md +34 -0
  431. package/knowledge/decisions/internals/workflow-core-never-imports-a-browser-driver.md +42 -0
  432. package/knowledge/decisions/internals/workflow-dsl-meta-separates-runtime-expressions-from-literals.md +38 -0
  433. package/knowledge/decisions/internals/workflow-features-resolve-scenarios-by-object-identity.md +29 -0
  434. package/knowledge/decisions/internals/workflow-graph-inline-and-queued-runs-share-one-planner.md +42 -0
  435. package/knowledge/decisions/internals/workflow-graph-node-notes-are-excluded-from-the-graph-hash.md +25 -0
  436. package/knowledge/decisions/internals/workflow-inline-runs-report-their-run-id-before-they-can-fail.md +29 -0
  437. package/knowledge/decisions/internals/workflow-invocation-id-is-the-dedupe-key-not-step-id.md +43 -0
  438. package/knowledge/decisions/internals/workflow-queued-step-dispatch-requires-an-explicit-opt-in.md +29 -0
  439. package/knowledge/decisions/internals/workflow-queues-are-per-workflow-by-default.md +42 -0
  440. package/knowledge/decisions/internals/workflow-repeated-step-names-get-an-ordinal-suffix.md +33 -0
  441. package/knowledge/decisions/internals/workflow-replay-reads-its-steps-once-and-caches-only-the-immutable-half.md +32 -0
  442. package/knowledge/decisions/internals/workflow-retries-are-owned-by-the-workflow-not-the-queue.md +31 -0
  443. package/knowledge/decisions/internals/workflow-run-capabilities-are-extensions-not-subclasses.md +39 -0
  444. package/knowledge/decisions/internals/workflow-run-mirror-is-never-a-source-of-truth.md +29 -0
  445. package/knowledge/decisions/internals/workflow-run-polling-backs-off-to-the-callers-ceiling.md +33 -0
  446. package/knowledge/decisions/internals/workflow-run-timeline-is-a-pure-fold-over-durable-history.md +37 -0
  447. package/knowledge/decisions/internals/workflow-scenario-assertions-never-retry-and-record-one-step.md +50 -0
  448. package/knowledge/decisions/internals/workflow-scenario-hooks-are-a-scenario-only-affordance.md +43 -0
  449. package/knowledge/decisions/internals/workflow-scenario-prose-is-rendered-from-typed-calls-not-parsed-from-english.md +32 -0
  450. package/knowledge/decisions/internals/workflow-scenario-quarantine-reason-lives-in-code.md +18 -0
  451. package/knowledge/decisions/internals/workflow-scenario-step-targets-are-string-literals-for-the-inspector.md +34 -0
  452. package/knowledge/decisions/internals/workflow-step-compensation-runs-as-its-own-durable-step.md +26 -0
  453. package/knowledge/decisions/internals/workflow-step-dispatch-failure-is-transient-not-a-run-failure.md +33 -0
  454. package/knowledge/decisions/internals/workflow-step-lock-is-held-only-to-claim-the-step.md +27 -0
  455. package/knowledge/decisions/internals/workflow-step-rpc-name-is-provenance-only.md +34 -0
  456. package/knowledge/decisions/internals/workflow-suspend-and-approval-reasons-are-durable-step-identities.md +38 -0
  457. package/knowledge/decisions/internals/workflow-suspended-runs-keep-their-in-process-context.md +30 -0
  458. package/knowledge/decisions/security/a-dropped-audit-write-is-always-logged.md +26 -0
  459. package/knowledge/decisions/security/actor-flow-missing-approval-decisions-default-to-denied.md +22 -0
  460. package/knowledge/decisions/security/actor-sign-in-is-proven-by-set-cookie-not-a-non-empty-jar.md +27 -0
  461. package/knowledge/decisions/security/actor-sign-in-only-works-for-actor-flagged-users.md +27 -0
  462. package/knowledge/decisions/security/addon-auth-and-tags-only-tighten.md +43 -0
  463. package/knowledge/decisions/security/addon-config-gates-apply-only-at-the-namespaced-rpc-boundary.md +52 -0
  464. package/knowledge/decisions/security/addon-scopes-are-resolved-where-the-function-runs.md +46 -0
  465. package/knowledge/decisions/security/ai-agent-approval-forwarding-requires-a-symbol-brand.md +27 -0
  466. package/knowledge/decisions/security/ai-agent-credential-requests-are-symbol-branded.md +37 -0
  467. package/knowledge/decisions/security/ai-agent-gate-requires-a-session-only-when-auth-is-true.md +31 -0
  468. package/knowledge/decisions/security/ai-agent-ownership-failures-never-echo-the-resource.md +23 -0
  469. package/knowledge/decisions/security/ai-agent-resume-re-runs-the-authorization-gate.md +22 -0
  470. package/knowledge/decisions/security/ai-agent-sessionless-deployments-have-no-thread-ownership.md +39 -0
  471. package/knowledge/decisions/security/ai-agent-thread-ownership-composes-the-session-principal.md +30 -0
  472. package/knowledge/decisions/security/ai-agent-tool-filtering-reads-the-live-function-config.md +24 -0
  473. package/knowledge/decisions/security/an-empty-owners-constraint-matches-nothing.md +30 -0
  474. package/knowledge/decisions/security/an-exposed-ungated-function-is-a-codegen-warning.md +49 -0
  475. package/knowledge/decisions/security/console-addon-privileged-functions-gate-themselves.md +76 -0
  476. package/knowledge/decisions/security/core-safe-fetch-blocks-ssrf-by-host-literal-not-dns.md +39 -0
  477. package/knowledge/decisions/security/core-secrets-use-a-per-secret-dek-wrapped-by-a-kek.md +37 -0
  478. package/knowledge/decisions/security/gateway-handlers-run-through-the-function-runner-gate.md +31 -0
  479. package/knowledge/decisions/security/gateway-middleware-sessions-must-be-bridged-onto-the-wire.md +30 -0
  480. package/knowledge/decisions/security/global-permissions-and-function-permissions-are-independent-gates.md +40 -0
  481. package/knowledge/decisions/security/http-error-detail-is-withheld-from-clients-in-production.md +33 -0
  482. package/knowledge/decisions/security/http-request-bodies-are-bounded-before-they-are-buffered.md +46 -0
  483. package/knowledge/decisions/security/index.md +55 -0
  484. package/knowledge/decisions/security/mcp-internal-error-details-are-double-gated-on-production.md +27 -0
  485. package/knowledge/decisions/security/passphrases-are-stretched-key-material-is-expanded.md +40 -0
  486. package/knowledge/decisions/security/permission-auth-filtering-requires-live-permission-functions.md +31 -0
  487. package/knowledge/decisions/security/pikku-carries-actor-scopes-as-data-and-the-app-grants-them.md +26 -0
  488. package/knowledge/decisions/security/queue-job-identities-are-signed-at-enqueue.md +69 -0
  489. package/knowledge/decisions/security/queue-jobs-carry-the-producers-pikku-user-id.md +39 -0
  490. package/knowledge/decisions/security/remote-addon-tokens-are-client-credentials-not-mesh-trust.md +34 -0
  491. package/knowledge/decisions/security/scaffold-features-are-authenticated-unless-opted-out.md +49 -0
  492. package/knowledge/decisions/security/scenario-step-functions-are-never-externally-invocable.md +30 -0
  493. package/knowledge/decisions/security/scope-resolution-happens-at-the-session-boundary-and-sync-never-deletes.md +28 -0
  494. package/knowledge/decisions/security/self-authentication-is-declared-not-detected.md +34 -0
  495. package/knowledge/decisions/security/signed-content-urls-bind-the-request-path.md +37 -0
  496. package/knowledge/decisions/security/webhook-bodies-are-signed-before-they-are-enqueued.md +25 -0
  497. package/knowledge/decisions/security/workflow-actor-steps-always-use-the-real-transport.md +34 -0
  498. package/knowledge/decisions/security/workflow-approval-payloads-are-validated-on-replay-inside-the-workflow.md +40 -0
  499. package/knowledge/decisions/security/workflow-queued-steps-rehydrate-their-session-from-the-run-wire.md +32 -0
  500. package/knowledge/decisions/security/workflow-scenario-sessions-are-isolated-per-actor-and-per-scenario.md +32 -0
  501. package/knowledge/decisions/security/workflow-scenario-steps-are-never-network-invocable.md +31 -0
  502. package/knowledge/index.md +24 -0
  503. package/knowledge/questions/index.md +15 -0
  504. package/package.json +4 -1
  505. package/run-tests.sh +0 -0
  506. package/src/crypto-utils.test.ts +460 -19
  507. package/src/crypto-utils.ts +283 -55
  508. package/src/data-classification.ts +1 -7
  509. package/src/dev/hot-reload.test.ts +0 -4
  510. package/src/dev/hot-reload.ts +11 -30
  511. package/src/dev/module-runner.ts +7 -32
  512. package/src/dev/reload-meta.ts +9 -29
  513. package/src/errors/error-handler.ts +20 -35
  514. package/src/errors/error.test.ts +30 -1
  515. package/src/errors/errors.ts +73 -157
  516. package/src/function/abort-scope.test.ts +97 -0
  517. package/src/function/abort-scope.ts +80 -0
  518. package/src/function/function-runner.test.ts +0 -7
  519. package/src/function/function-runner.ts +62 -32
  520. package/src/function/functions.types.ts +56 -136
  521. package/src/function/list.types.test.ts +3 -25
  522. package/src/function/list.types.ts +12 -62
  523. package/src/handle-error.ts +0 -18
  524. package/src/index.ts +60 -1
  525. package/src/middleware/auth-apikey.test.ts +0 -1
  526. package/src/middleware/auth-apikey.ts +0 -17
  527. package/src/middleware/auth-bearer.test.ts +0 -3
  528. package/src/middleware/auth-bearer.ts +3 -40
  529. package/src/middleware/auth-cookie.test.ts +0 -6
  530. package/src/middleware/auth-cookie.ts +2 -26
  531. package/src/middleware/cors.test.ts +34 -0
  532. package/src/middleware/cors.ts +12 -33
  533. package/src/middleware/remote-auth.test.ts +24 -9
  534. package/src/middleware/remote-auth.ts +10 -2
  535. package/src/middleware/telemetry.ts +2 -31
  536. package/src/middleware-runner.test.ts +0 -2
  537. package/src/middleware-runner.ts +5 -74
  538. package/src/permissions.test.ts +30 -0
  539. package/src/permissions.ts +24 -74
  540. package/src/pikku-request.ts +0 -6
  541. package/src/pikku-state.ts +2 -30
  542. package/src/production-barrels-stay-lean.test.ts +110 -0
  543. package/src/remote.test.ts +172 -0
  544. package/src/remote.ts +17 -7
  545. package/src/schema.ts +5 -39
  546. package/src/scopes.ts +7 -48
  547. package/src/services/ai-agent-runner-service.ts +20 -0
  548. package/src/services/ai-embedding-service.ts +3 -25
  549. package/src/services/audit-service.ts +1 -2
  550. package/src/services/content-service.ts +1 -46
  551. package/src/services/credential-service.ts +3 -40
  552. package/src/services/credential-wire-service.test.ts +0 -2
  553. package/src/services/deployment-service.ts +3 -9
  554. package/src/services/gateway-service.ts +0 -15
  555. package/src/services/{http-scenario-actors-converse.test.ts → http-personas-converse.test.ts} +38 -9
  556. package/src/services/{http-scenario-actors.test.ts → http-personas.test.ts} +39 -22
  557. package/src/services/{http-scenario-actors.ts → http-personas.ts} +85 -45
  558. package/src/services/in-memory-queue-service.ts +1 -15
  559. package/src/services/in-memory-trigger-service.ts +1 -18
  560. package/src/services/in-memory-workflow-service.test.ts +0 -13
  561. package/src/services/in-memory-workflow-service.ts +4 -38
  562. package/src/services/index.ts +20 -15
  563. package/src/services/istanbul-coverage-service.ts +2 -8
  564. package/src/services/jwt-service.ts +1 -16
  565. package/src/services/local-content.test.ts +159 -27
  566. package/src/services/local-content.ts +55 -23
  567. package/src/services/local-gateway-service.ts +2 -17
  568. package/src/services/local-secrets.ts +0 -4
  569. package/src/services/logger-console.test.ts +0 -1
  570. package/src/services/logger-console.ts +3 -7
  571. package/src/services/logger.ts +2 -37
  572. package/src/services/meta-service.test.ts +1 -5
  573. package/src/services/meta-service.ts +41 -61
  574. package/src/services/{scenario-actors-service.ts → personas-service.ts} +48 -43
  575. package/src/services/pikku-user-id.ts +0 -4
  576. package/src/services/queue-webhook-service.ts +9 -41
  577. package/src/services/scheduler-service.ts +1 -50
  578. package/src/services/schema-service.ts +1 -24
  579. package/src/services/scope-service.ts +50 -34
  580. package/src/services/scoped-secret-service.ts +0 -4
  581. package/src/services/secret-host-binding.test.ts +138 -0
  582. package/src/services/secret-host-binding.ts +51 -0
  583. package/src/services/secret-service.ts +5 -33
  584. package/src/services/secretless.test.ts +54 -0
  585. package/src/services/secretless.ts +29 -0
  586. package/src/services/stub-tracker.ts +8 -18
  587. package/src/services/system-role-guard.test.ts +93 -0
  588. package/src/services/system-role-guard.ts +71 -0
  589. package/src/services/trigger-service.ts +0 -12
  590. package/src/services/typed-secret-service.ts +1 -7
  591. package/src/services/v8-coverage-service.ts +3 -6
  592. package/src/services/variables-service.ts +1 -8
  593. package/src/services/webhook-service.ts +19 -63
  594. package/src/services/workflow-service.ts +3 -20
  595. package/src/testing/service-tests.ts +0 -26
  596. package/src/time-utils.ts +1 -19
  597. package/src/types/core.types.ts +116 -229
  598. package/src/types/state.types.ts +7 -9
  599. package/src/utils/hmac.ts +4 -10
  600. package/src/utils/safe-fetch.ts +13 -54
  601. package/src/utils.test.ts +11 -2
  602. package/src/utils.ts +6 -15
  603. package/src/wirings/actor-flow/actor-flow.types.ts +1 -34
  604. package/src/wirings/actor-flow/index.ts +0 -9
  605. package/src/wirings/actor-flow/run-conversation.test.ts +11 -6
  606. package/src/wirings/actor-flow/run-conversation.ts +19 -12
  607. package/src/wirings/ai-agent/ai-agent-agui.test.ts +75 -10
  608. package/src/wirings/ai-agent/ai-agent-agui.ts +36 -17
  609. package/src/wirings/ai-agent/ai-agent-helpers.ts +20 -0
  610. package/src/wirings/ai-agent/ai-agent-interrupt.test.ts +842 -0
  611. package/src/wirings/ai-agent/ai-agent-interrupt.ts +399 -0
  612. package/src/wirings/ai-agent/ai-agent-memory.ts +0 -2
  613. package/src/wirings/ai-agent/ai-agent-model-config.ts +1 -9
  614. package/src/wirings/ai-agent/ai-agent-prepare.test.ts +202 -31
  615. package/src/wirings/ai-agent/ai-agent-prepare.ts +82 -138
  616. package/src/wirings/ai-agent/ai-agent-registry.test.ts +191 -6
  617. package/src/wirings/ai-agent/ai-agent-registry.ts +18 -1
  618. package/src/wirings/ai-agent/ai-agent-resume-authorization.test.ts +0 -2
  619. package/src/wirings/ai-agent/ai-agent-runner.test.ts +11 -9
  620. package/src/wirings/ai-agent/ai-agent-runner.ts +67 -33
  621. package/src/wirings/ai-agent/ai-agent-stream.test.ts +205 -103
  622. package/src/wirings/ai-agent/ai-agent-stream.ts +192 -75
  623. package/src/wirings/ai-agent/ai-agent-thread-ownership.test.ts +301 -0
  624. package/src/wirings/ai-agent/ai-agent.types.ts +85 -4
  625. package/src/wirings/ai-agent/index.ts +35 -3
  626. package/src/wirings/ai-agent/voice-input.test.ts +72 -7
  627. package/src/wirings/ai-agent/voice-input.ts +48 -3
  628. package/src/wirings/ai-agent/voice-output.test.ts +422 -0
  629. package/src/wirings/ai-agent/voice-output.ts +216 -56
  630. package/src/wirings/channel/channel-common.ts +15 -20
  631. package/src/wirings/channel/channel-handler.test.ts +50 -0
  632. package/src/wirings/channel/channel-handler.ts +32 -11
  633. package/src/wirings/channel/channel-host-rpc.test.ts +150 -0
  634. package/src/wirings/channel/channel-host-rpc.ts +69 -0
  635. package/src/wirings/channel/channel-middleware-runner.test.ts +0 -1
  636. package/src/wirings/channel/channel-middleware-runner.ts +0 -12
  637. package/src/wirings/channel/channel-rpc-registry.ts +116 -0
  638. package/src/wirings/channel/channel-rpc-responder.ts +117 -0
  639. package/src/wirings/channel/channel-rpc-service.ts +146 -0
  640. package/src/wirings/channel/channel-rpc-validators.ts +65 -0
  641. package/src/wirings/channel/channel-rpc.test.ts +820 -0
  642. package/src/wirings/channel/channel-rpc.ts +5 -0
  643. package/src/wirings/channel/channel-rpc.types.ts +150 -0
  644. package/src/wirings/channel/channel-runner.ts +0 -14
  645. package/src/wirings/channel/channel-store.ts +0 -10
  646. package/src/wirings/channel/channel.types.ts +19 -8
  647. package/src/wirings/channel/define-channel-routes.ts +0 -20
  648. package/src/wirings/channel/eventhub-service.ts +0 -18
  649. package/src/wirings/channel/index.ts +35 -0
  650. package/src/wirings/channel/local/local-channel-handler.ts +3 -1
  651. package/src/wirings/channel/local/local-channel-runner.test.ts +0 -10
  652. package/src/wirings/channel/local/local-channel-runner.ts +3 -1
  653. package/src/wirings/channel/local/local-eventhub-service.test.ts +0 -13
  654. package/src/wirings/channel/local/local-eventhub-service.ts +2 -37
  655. package/src/wirings/channel/log-channels.ts +0 -4
  656. package/src/wirings/channel/pikku-abstract-channel-handler.test.ts +83 -2
  657. package/src/wirings/channel/pikku-abstract-channel-handler.ts +7 -0
  658. package/src/wirings/channel/serverless/serverless-channel-runner.ts +2 -5
  659. package/src/wirings/cli/channel/cli-approval.test.ts +177 -0
  660. package/src/wirings/cli/channel/cli-approval.ts +135 -0
  661. package/src/wirings/cli/channel/cli-channel-runner.ts +4 -26
  662. package/src/wirings/cli/channel/cli-raw-channel-runner.test.ts +169 -0
  663. package/src/wirings/cli/channel/cli-raw-channel-runner.ts +59 -16
  664. package/src/wirings/cli/channel/cli-raw-client-runner.test.ts +480 -0
  665. package/src/wirings/cli/channel/cli-raw-client-runner.ts +155 -0
  666. package/src/wirings/cli/channel/index.ts +9 -0
  667. package/src/wirings/cli/cli-runner.test.ts +0 -1
  668. package/src/wirings/cli/cli-runner.ts +46 -88
  669. package/src/wirings/cli/cli.types.ts +14 -3
  670. package/src/wirings/cli/command-parser.test.ts +0 -4
  671. package/src/wirings/cli/command-parser.ts +11 -91
  672. package/src/wirings/cli/define-cli-commands.ts +1 -17
  673. package/src/wirings/credential/credential.types.ts +0 -12
  674. package/src/wirings/credential/{wire-credential.ts → define-credential.ts} +7 -7
  675. package/src/wirings/credential/index.ts +1 -1
  676. package/src/wirings/credential/validate-credential-definitions.ts +2 -4
  677. package/src/wirings/gateway/gateway-runner.test.ts +1 -21
  678. package/src/wirings/gateway/gateway-runner.ts +8 -110
  679. package/src/wirings/gateway/gateway.types.ts +7 -80
  680. package/src/wirings/http/http-routes.test.ts +0 -3
  681. package/src/wirings/http/http-routes.ts +0 -86
  682. package/src/wirings/http/http-runner.test.ts +0 -1
  683. package/src/wirings/http/http-runner.ts +8 -167
  684. package/src/wirings/http/http.types.ts +15 -62
  685. package/src/wirings/http/log-http-routes.ts +0 -4
  686. package/src/wirings/http/pikku-fetch-http-request.test.ts +2 -10
  687. package/src/wirings/http/pikku-fetch-http-request.ts +0 -58
  688. package/src/wirings/http/pikku-fetch-http-response.test.ts +1 -1
  689. package/src/wirings/http/pikku-fetch-http-response.ts +0 -3
  690. package/src/wirings/http/routers/path-to-regex.test.ts +4 -17
  691. package/src/wirings/http/routers/path-to-regex.ts +2 -13
  692. package/src/wirings/http/web-request.test.ts +33 -2
  693. package/src/wirings/http/web-request.ts +30 -17
  694. package/src/wirings/mcp/mcp-endpoint-registry.test.ts +0 -1
  695. package/src/wirings/mcp/mcp-runner.ts +2 -17
  696. package/src/wirings/mcp/mcp.types.ts +7 -42
  697. package/src/wirings/oauth2/oauth2.types.ts +0 -30
  698. package/src/wirings/persona/define-personas.ts +29 -0
  699. package/src/wirings/persona/index.ts +62 -0
  700. package/src/wirings/persona/persona-email.ts +87 -0
  701. package/src/wirings/persona/persona-environments.test.ts +183 -0
  702. package/src/wirings/persona/persona-environments.ts +138 -0
  703. package/src/wirings/persona/persona-mailbox.ts +156 -0
  704. package/src/wirings/persona/persona.test.ts +220 -0
  705. package/src/wirings/persona/persona.types.ts +131 -0
  706. package/src/wirings/persona/validate-personas.ts +133 -0
  707. package/src/wirings/queue/index.ts +13 -3
  708. package/src/wirings/queue/queue-identity.test.ts +453 -0
  709. package/src/wirings/queue/queue-identity.ts +173 -0
  710. package/src/wirings/queue/queue-runner.ts +12 -31
  711. package/src/wirings/queue/queue.types.ts +19 -89
  712. package/src/wirings/queue/register-queue-helper.ts +0 -14
  713. package/src/wirings/queue/signed-queue-service.ts +59 -0
  714. package/src/wirings/queue/validate-worker-config.ts +2 -28
  715. package/src/wirings/role/define-system-role.ts +33 -0
  716. package/src/wirings/role/index.ts +13 -0
  717. package/src/wirings/role/role.test.ts +104 -0
  718. package/src/wirings/role/role.types.ts +47 -0
  719. package/src/wirings/role/validate-role-definitions.ts +93 -0
  720. package/src/wirings/rpc/addon-auth-tags.test.ts +223 -0
  721. package/src/wirings/rpc/addon-runner.ts +0 -56
  722. package/src/wirings/rpc/addon-scopes.test.ts +225 -0
  723. package/src/wirings/rpc/remote-addon-auth.ts +1 -13
  724. package/src/wirings/rpc/rpc-runner.test.ts +186 -2
  725. package/src/wirings/rpc/rpc-runner.ts +145 -127
  726. package/src/wirings/rpc/rpc-types.ts +11 -6
  727. package/src/wirings/rpc/wire-addon.test.ts +43 -1
  728. package/src/wirings/rpc/wire-addon.ts +99 -0
  729. package/src/wirings/rpc/wire-remote-addon.ts +9 -29
  730. package/src/wirings/scheduler/log-schedulers.ts +0 -4
  731. package/src/wirings/scheduler/scheduler-runner.test.ts +1 -8
  732. package/src/wirings/scheduler/scheduler-runner.ts +0 -2
  733. package/src/wirings/scheduler/scheduler.types.ts +1 -14
  734. package/src/wirings/scope/{wire-scope.ts → define-scope.ts} +5 -6
  735. package/src/wirings/scope/index.ts +1 -1
  736. package/src/wirings/scope/scope.test.ts +1 -2
  737. package/src/wirings/scope/scope.types.ts +7 -9
  738. package/src/wirings/scope/validate-scope-definitions.ts +3 -21
  739. package/src/wirings/secret/index.ts +1 -1
  740. package/src/wirings/secret/secret.types.ts +19 -15
  741. package/src/wirings/secret/validate-secret-definitions.ts +2 -4
  742. package/src/wirings/trigger/trigger-runner.ts +1 -27
  743. package/src/wirings/trigger/trigger.types.ts +1 -82
  744. package/src/wirings/variable/index.ts +1 -1
  745. package/src/wirings/variable/validate-variable-definitions.ts +2 -4
  746. package/src/wirings/variable/variable.types.ts +1 -13
  747. package/src/wirings/virtual-user/index.ts +76 -0
  748. package/src/wirings/virtual-user/run-virtual-user.test.ts +765 -0
  749. package/src/wirings/virtual-user/run-virtual-user.ts +671 -0
  750. package/src/wirings/virtual-user/virtual-user-agents.test.ts +65 -0
  751. package/src/wirings/virtual-user/virtual-user-agents.ts +57 -0
  752. package/src/wirings/virtual-user/virtual-user-catalogue.test.ts +215 -0
  753. package/src/wirings/virtual-user/virtual-user-catalogue.ts +184 -0
  754. package/src/wirings/virtual-user/virtual-user-derive.test.ts +398 -0
  755. package/src/wirings/virtual-user/virtual-user-derive.ts +173 -0
  756. package/src/wirings/virtual-user/virtual-user-dispositions.test.ts +63 -0
  757. package/src/wirings/virtual-user/virtual-user-dispositions.ts +213 -0
  758. package/src/wirings/virtual-user/virtual-user-intents.test.ts +208 -0
  759. package/src/wirings/virtual-user/virtual-user-intents.ts +185 -0
  760. package/src/wirings/virtual-user/virtual-user-rng.test.ts +72 -0
  761. package/src/wirings/virtual-user/virtual-user-rng.ts +50 -0
  762. package/src/wirings/virtual-user/virtual-user-target.ts +47 -0
  763. package/src/wirings/virtual-user/virtual-user.types.ts +219 -0
  764. package/src/wirings/workflow/dsl/workflow-dsl.types.ts +5 -4
  765. package/src/wirings/workflow/dsl/workflow-runner.ts +0 -4
  766. package/src/wirings/workflow/feature.ts +0 -19
  767. package/src/wirings/workflow/graph/graph-node.ts +0 -136
  768. package/src/wirings/workflow/graph/graph-runner.test.ts +20 -19
  769. package/src/wirings/workflow/graph/graph-runner.ts +6 -41
  770. package/src/wirings/workflow/graph/wire-workflow-graph.ts +0 -4
  771. package/src/wirings/workflow/graph/workflow-graph.types.ts +0 -58
  772. package/src/wirings/workflow/index.ts +10 -44
  773. package/src/wirings/workflow/pikku-scenario-service.ts +235 -52
  774. package/src/wirings/workflow/pikku-workflow-service.test.ts +0 -39
  775. package/src/wirings/workflow/pikku-workflow-service.ts +77 -674
  776. package/src/wirings/workflow/run-timeline.test.ts +7 -19
  777. package/src/wirings/workflow/run-timeline.ts +0 -56
  778. package/src/wirings/workflow/scenario-cookie-jar.test.ts +0 -1
  779. package/src/wirings/workflow/scenario-cookie-jar.ts +0 -25
  780. package/src/wirings/workflow/scenario-expectations.test.ts +2 -7
  781. package/src/wirings/workflow/scenario-hooks.test.ts +2 -7
  782. package/src/wirings/workflow/scenario-poll.test.ts +0 -2
  783. package/src/wirings/workflow/scenario-poll.ts +0 -15
  784. package/src/wirings/workflow/scenario-prose.ts +0 -28
  785. package/src/wirings/workflow/scenario-service.test.ts +2 -9
  786. package/src/wirings/workflow/scenario-step-guards.ts +1 -14
  787. package/src/wirings/workflow/scenario-step.test.ts +159 -14
  788. package/src/wirings/workflow/scenario-step.types.ts +82 -6
  789. package/src/wirings/workflow/scenario-surface.test.ts +145 -0
  790. package/src/wirings/workflow/scenario-surface.ts +71 -0
  791. package/src/wirings/workflow/workflow-dispatch-durability.test.ts +14 -15
  792. package/src/wirings/workflow/workflow-dispatch-payload.test.ts +0 -4
  793. package/src/wirings/workflow/workflow-inline-authority.test.ts +169 -0
  794. package/src/wirings/workflow/workflow-invocation-id.test.ts +0 -2
  795. package/src/wirings/workflow/workflow-invocation-id.ts +2 -22
  796. package/src/wirings/workflow/workflow-mirror.test.ts +0 -7
  797. package/src/wirings/workflow/workflow-on-error.test.ts +0 -9
  798. package/src/wirings/workflow/workflow-queue-workers.ts +0 -21
  799. package/src/wirings/workflow/workflow-replay-snapshot.test.ts +8 -7
  800. package/src/wirings/workflow/workflow-retry-policy.test.ts +0 -5
  801. package/src/wirings/workflow/workflow-run-context.test.ts +5 -10
  802. package/src/wirings/workflow/workflow-run-polling.test.ts +0 -5
  803. package/src/wirings/workflow/workflow-step-ordinal.test.ts +19 -4
  804. package/src/wirings/workflow/workflow-step-session.test.ts +0 -7
  805. package/src/wirings/workflow/workflow.types.ts +0 -203
  806. package/tsconfig.tsbuildinfo +1 -1
  807. package/src/middleware/timeout.ts +0 -22
  808. package/src/pikku-response.ts +0 -5
  809. package/src/wirings/mcp/mcp-endpoint-registry.test.d.ts +0 -1
  810. package/src/wirings/workflow/dsl/index.ts +0 -36
  811. package/src/wirings/workflow/graph/index.ts +0 -15
@@ -6,118 +6,72 @@ import { verifyScopes } from '../../scopes.js';
6
6
  import { pikkuState, getSingletonServices } from '../../pikku-state.js';
7
7
  import { createMiddlewareSessionWireProps } from '../../services/user-session-service.js';
8
8
  import { randomUUID } from './ai-agent-utils.js';
9
+ import { awaitPendingInterruptNote } from './ai-agent-interrupt.js';
9
10
  import { streamAIAgent } from './ai-agent-stream.js';
10
11
  import { runAIAgent } from './ai-agent-runner.js';
11
12
  import { resolveNamespace, ContextAwareRPCService, } from '../../wirings/rpc/rpc-runner.js';
12
13
  import { getOrCreatePackageSingletonServices } from '../../wirings/rpc/addon-runner.js';
13
14
  import { resolveMemoryServices, loadContextMessages, trimMessages, } from './ai-agent-memory.js';
14
15
  import { resolveModelConfig } from './ai-agent-model-config.js';
15
- /**
16
- * The ownership key for a thread/run: the trusted principal (the authenticated
17
- * `session.userId` for `'user'` scope, or `session.orgId` for `'org'` scope)
18
- * composed with the client-supplied `resourceId` as a sub-partition —
19
- * `principal:resourceId`. Because the principal is always the prefix, a client
20
- * `resourceId` can sub-divide within the caller's own boundary but can never
21
- * widen access to another user's or org's threads.
22
- *
23
- * Idempotent: a value that is already within the caller's namespace (top-level
24
- * re-entry, sub-agent recursion, or resume, which all pass an already-composite
25
- * `resourceId`) is returned unchanged rather than double-composed.
26
- *
27
- * `'org'` scope with no session org throws {@link ForbiddenError} — falling back
28
- * to a bare/shared key would leak across organizations. Sessionless `'user'`
29
- * wirings have no trusted principal and fall back to the requested `resourceId`
30
- * as a best-effort partition key.
31
- */
32
- export function resolveOwnerResourceId(params, sessionScope, requestedResourceId) {
16
+ export function resolveSessionPrincipal(params, sessionScope) {
33
17
  const session = params.sessionService?.get();
34
- let principal;
35
18
  if ((sessionScope ?? 'user') === 'org') {
36
19
  if (!session?.orgId) {
37
20
  throw new ForbiddenError('This agent is org-scoped but the session has no organization');
38
21
  }
39
- principal = session.orgId;
22
+ return session.orgId;
40
23
  }
41
- else {
42
- principal = session?.userId;
24
+ return session?.userId;
25
+ }
26
+ export function resolveOwnerResourceId(params, sessionScope, requestedResourceId) {
27
+ const principal = resolveSessionPrincipal(params, sessionScope);
28
+ if (!principal) {
29
+ params.anonymousOwnerResourceId ??= `anon-${randomUUID()}`;
30
+ return params.anonymousOwnerResourceId;
43
31
  }
44
- if (!principal)
45
- return requestedResourceId;
46
32
  if (requestedResourceId === principal ||
47
33
  requestedResourceId.startsWith(`${principal}:`)) {
48
34
  return requestedResourceId;
49
35
  }
50
36
  return `${principal}:${requestedResourceId}`;
51
37
  }
52
- /** The declared {@link SessionScope} for an agent, defaulting to `'user'`. */
38
+ export function assertResourcePrincipalOwner(params, sessionScope, storedResourceId, kind) {
39
+ const principal = resolveSessionPrincipal(params, sessionScope);
40
+ if (!principal || !isOwnedByPrincipal(storedResourceId, principal)) {
41
+ throw new ForbiddenError(`Not authorized to access this ${kind}`);
42
+ }
43
+ }
53
44
  export function agentSessionScope(agentName) {
54
45
  return resolveAgent(agentName).agent.sessionScope ?? 'user';
55
46
  }
56
- /**
57
- * Enforce that a stored thread/run belongs to the caller's owner resource,
58
- * throwing {@link ForbiddenError} (without echoing the id, to avoid an
59
- * existence oracle) on a mismatch.
60
- */
61
47
  export function assertResourceOwner(ownerResourceId, storedResourceId, kind) {
62
48
  if (storedResourceId !== ownerResourceId) {
63
49
  throw new ForbiddenError(`Not authorized to access this ${kind}`);
64
50
  }
65
51
  }
66
- /** A session's trusted principals, in the order they may be read as. */
67
52
  export function sessionPrincipals(session) {
68
53
  return [session?.userId, session?.orgId].filter((principal) => Boolean(principal));
69
54
  }
70
- /**
71
- * Whether `storedResourceId` belongs to `principal` under the composition
72
- * {@link resolveOwnerResourceId} performs — either the bare principal or one of
73
- * its `principal:` sub-partitions. The `:` is required so that `alice` does not
74
- * match a `alice-evil:…` lookalike.
75
- */
76
55
  export function isOwnedByPrincipal(storedResourceId, principal) {
77
56
  return (storedResourceId === principal ||
78
57
  storedResourceId.startsWith(`${principal}:`));
79
58
  }
80
- /**
81
- * The `owners` constraint to pass to `AgentRunService.listThreads` for a caller.
82
- *
83
- * Returns `undefined` — not `[]` — for a session with no principal, because an
84
- * empty list means "match nothing" whereas a sessionless deployment (agent
85
- * `no-auth`) has no ownership model to constrain by. Keeping that carve-out here
86
- * rather than at each call site stops it from being re-derived inconsistently.
87
- */
88
59
  export function threadOwnerConstraint(session) {
89
- const principals = sessionPrincipals(session);
90
- return principals.length > 0 ? principals : undefined;
60
+ return sessionPrincipals(session);
91
61
  }
92
- /**
93
- * Whether a stored thread/run may be read by the caller. Shaped as a predicate
94
- * so it can back a `pikkuPermission` — authorization belongs in a function's
95
- * `permissions` field, never in its body.
96
- *
97
- * Unlike {@link assertResourceOwner}, which compares against a single composed
98
- * owner key on the run path, this guards the thread-management reads where the
99
- * caller supplies only a `threadId` — so ownership has to be derived from the
100
- * session rather than from the request.
101
- *
102
- * A session with no principal means the deployment opted out of authorization
103
- * (agent `no-auth`), so there is no ownership model to enforce and access is not
104
- * gated — mirroring {@link resolveOwnerResourceId}'s sessionless fallback to a
105
- * bare resourceId.
106
- */
107
62
  export function canAccessThread(storedResourceId, session) {
108
63
  const principals = sessionPrincipals(session);
109
64
  if (principals.length === 0)
110
- return true;
65
+ return false;
111
66
  return principals.some((principal) => isOwnedByPrincipal(storedResourceId, principal));
112
67
  }
68
+ export const APPROVAL_REQUIRED = Symbol('pikku.ai.approvalRequired');
113
69
  /**
114
- * Non-forgeable brand for the sub-agent approval marker. Only framework code
115
- * (the delegating sub-agent tools below) sets this Symbol on a tool result; a
116
- * sub-agent's LLM-shaped `result.object` plain JSON cannot carry a Symbol,
117
- * so `checkForApprovals` trusts the brand rather than the `__approvalRequired`
118
- * string key to decide an approval must be surfaced.
70
+ * In-process brand proving a credential request was produced by pikku itself and
71
+ * not by tool output an attacker can influence. Never serialized — a value that
72
+ * has crossed a JSON boundary has lost the brand and is treated as untrusted.
119
73
  */
120
- export const APPROVAL_REQUIRED = Symbol('pikku.ai.approvalRequired');
74
+ export const CREDENTIAL_REQUIRED = Symbol('pikku.ai.credentialRequired');
121
75
  export class ToolApprovalRequired extends PikkuError {
122
76
  toolCallId;
123
77
  toolName;
@@ -154,10 +108,6 @@ export class ToolCredentialRequired extends PikkuError {
154
108
  this.connectUrl = connectUrl;
155
109
  }
156
110
  }
157
- /**
158
- * Given a list of tool names (e.g. ["oauth-api:getProfile"]),
159
- * returns the wire OAuth credentials required by their addons.
160
- */
161
111
  export function getAddonCredentialRequirements(toolNames) {
162
112
  const requirements = new Map();
163
113
  for (const toolName of toolNames) {
@@ -211,26 +161,6 @@ export const resolveAgent = (agentName) => {
211
161
  }
212
162
  throw new Error(`AI agent not found: ${agentName}`);
213
163
  };
214
- /**
215
- * Enforces an agent's own authorization before it runs: session presence
216
- * (`auth`), then `scopes`, then `permissions`.
217
- *
218
- * The ordering mirrors the function runner — scopes are an AND gate checked
219
- * first, so they can only ever narrow access, and a missing scope short-circuits
220
- * before any permission function does I/O.
221
- *
222
- * `auth` follows `pikkuSessionlessFunc` rather than `pikkuFunc`: a session is
223
- * required only when `auth: true` is set explicitly. An agent is normally
224
- * reached from a function that has already enforced its own auth, and agents are
225
- * also run from genuinely sessionless contexts (crons, queue workers), so
226
- * requiring a session by default would reject those without adding a meaningful
227
- * gate. `scopes` and `permissions` are always enforced when declared.
228
- *
229
- * Globals are evaluated here too (via {@link runPermissions}) rather than being
230
- * assumed to have already run: an agent is reachable from entry points that do
231
- * not go through the function runner, and re-evaluating an AND gate of
232
- * side-effect-free predicates is idempotent.
233
- */
234
164
  export async function assertAgentAuthorized(agent, params, packageName) {
235
165
  const session = params.sessionService
236
166
  ? await params.sessionService.get()
@@ -322,31 +252,13 @@ export function createScopedChannel(parent, agentName, session) {
322
252
  setState: (s) => parent.setState(s),
323
253
  getState: () => parent.getState(),
324
254
  clearState: () => parent.clearState(),
255
+ remote: (funcName, data) => parent.remote(funcName, data),
325
256
  };
326
257
  }
327
- /**
328
- * Build the run input for a delegated sub-agent.
329
- *
330
- * `context` is the PARENT run's identifier block (the "Current context" text
331
- * with organizationId, project/stage ids). A sub-agent's tool-call schema only
332
- * carries { message, session }, so unless the sub-agent inherits the parent's
333
- * context it never sees the authoritative ids — it depends on the model
334
- * re-typing them into `message`, which weak models botch, causing
335
- * schema/permission rejections and retry loops. Forwarding it here is the
336
- * regression this seam guards.
337
- */
338
258
  export function buildSubAgentRunInput(message, threadId, resourceId, parentContext) {
339
259
  return { message, threadId, resourceId, context: parentContext };
340
260
  }
341
- export async function buildToolDefs(params, agentSessionMap, resourceId, agentName, packageName, streamContext, aiMiddlewares, agentMode,
342
- // The parent run's `context` (the "Current context" identifier block). A
343
- // delegated sub-agent's tool-call input schema only carries { message,
344
- // session }, so without inheriting this the sub-agent never sees the
345
- // authoritative ids (organizationId, project/stage ids) — it depends on the
346
- // model re-typing them into `message`, which weak models botch, causing
347
- // schema/permission rejections and retry loops. Forward it so the sub-agent
348
- // gets the same context block in its instructions.
349
- parentContext) {
261
+ export async function buildToolDefs(params, agentSessionMap, resourceId, agentName, packageName, streamContext, aiMiddlewares, agentMode, parentContext) {
350
262
  const singletonServices = getSingletonServices();
351
263
  const tools = [];
352
264
  const missingRpcs = [];
@@ -354,7 +266,22 @@ parentContext) {
354
266
  const meta = pikkuState(packageName, 'agent', 'agentsMeta')[agentName];
355
267
  if (!meta)
356
268
  return { tools, missingRpcs };
357
- // Get session for permission filtering
269
+ /**
270
+ * A tool's description is what the model is told it does, and the main thing
271
+ * it chooses between tools on. It does not survive into the meta registered at
272
+ * boot: `description` is classed as a verbose field, so the bundled copy has
273
+ * it stripped and `fnMeta.description` is always undefined — every tool was
274
+ * being offered under its own bare name regardless of what its author wrote.
275
+ *
276
+ * `getFunctionsMeta` reads the verbose file and falls back to the minimal one,
277
+ * recovering the authored description wherever the generated `.pikku`
278
+ * directory is readable. Where it is not — no `metaService`, or a deployment
279
+ * shipping only the stripped copy — tools fall back to their name, which is
280
+ * what they did before this lookup existed.
281
+ */
282
+ const describedFunctions = await singletonServices.metaService
283
+ ?.getFunctionsMeta()
284
+ .catch(() => undefined);
358
285
  const session = params.sessionService
359
286
  ? await params.sessionService.get()
360
287
  : null;
@@ -389,10 +316,6 @@ parentContext) {
389
316
  missingRpcs.push(toolName);
390
317
  continue;
391
318
  }
392
- // Filter out tools the user doesn't have auth for. The `pikkuAuth` brand
393
- // only survives on the live permission objects in the function config, so
394
- // the check reads those rather than the metadata (whose by-name registry
395
- // is never populated, which would let every gated tool through).
396
319
  if (fnMeta.permissions?.length) {
397
320
  if (!session)
398
321
  continue;
@@ -415,7 +338,6 @@ parentContext) {
415
338
  }
416
339
  const needsApproval = approvalPolicy === 'all' ||
417
340
  (approvalPolicy === 'explicit' && fnMeta?.approvalRequired);
418
- // Build approvalDescriptionFn if the function has an approvalDescription configured
419
341
  let approvalDescriptionFn;
420
342
  if (needsApproval && pikkuFuncId) {
421
343
  const funcConfig = pikkuState(resolvedPkg, 'function', 'functions').get(pikkuFuncId);
@@ -445,10 +367,13 @@ parentContext) {
445
367
  }
446
368
  tools.push({
447
369
  name: toolName.replaceAll('@', '_').replaceAll(':', '__'),
448
- description: fnMeta?.description || fnMeta?.title || toolName,
370
+ description: describedFunctions?.[pikkuFuncId]?.description ||
371
+ fnMeta?.description ||
372
+ toolName,
449
373
  inputSchema,
450
374
  needsApproval: needsApproval || undefined,
451
375
  approvalDescriptionFn,
376
+ readonly: fnMeta?.readonly || undefined,
452
377
  execute: async (toolInput) => {
453
378
  const wire = params.sessionService
454
379
  ? { ...createMiddlewareSessionWireProps(params.sessionService) }
@@ -467,8 +392,6 @@ parentContext) {
467
392
  singletonServices.logger.warn(`Sub-agent '${subAgentName}' not found in agent registry`);
468
393
  continue;
469
394
  }
470
- // Filter out sub-agents the user doesn't have auth for, reading the live
471
- // agent config for the same reason the tool path does.
472
395
  if (subMeta.permissions?.length) {
473
396
  if (!session)
474
397
  continue;
@@ -513,8 +436,6 @@ parentContext) {
513
436
  input: message,
514
437
  });
515
438
  const subChannel = createScopedChannel(channel, subAgentName, session);
516
- // In supervise mode, suppress sub-agent text from reaching the client.
517
- // Approvals still flow through normally.
518
439
  const effectiveChannel = isDelegate
519
440
  ? subChannel
520
441
  : {
@@ -545,7 +466,6 @@ parentContext) {
545
466
  });
546
467
  return resultText;
547
468
  }
548
- // No stream context: sub-agent runs non-streaming
549
469
  const result = await runAIAgent(subAgentName, buildSubAgentRunInput(message, threadId, resourceId, parentContext), params, agentSessionMap);
550
470
  if (result.status === 'suspended' &&
551
471
  result.pendingApprovals?.length) {
@@ -610,11 +530,6 @@ parentContext) {
610
530
  });
611
531
  }
612
532
  }
613
- // A tool's execute() can throw (bad input, RPC failure, DB error, ...). The AI
614
- // SDK catches that at the tool-call boundary and turns it into a conversational
615
- // "tool error" reply — without this, the exception never reaches pikku's own
616
- // logger, so a failing tool is undiagnosable server-side. Log unconditionally,
617
- // even when no aiMiddleware afterToolCall hook is registered to see it.
618
533
  for (const tool of tools) {
619
534
  const originalExecute = tool.execute;
620
535
  tool.execute = async (toolInput) => {
@@ -622,6 +537,13 @@ parentContext) {
622
537
  return await originalExecute(toolInput);
623
538
  }
624
539
  catch (err) {
540
+ if (err?.payload?.error === 'missing_credential') {
541
+ return {
542
+ [CREDENTIAL_REQUIRED]: true,
543
+ __credentialRequired: true,
544
+ ...err.payload,
545
+ };
546
+ }
625
547
  singletonServices.logger.error(`AI agent tool '${tool.name}' threw during execute()`, err);
626
548
  throw err;
627
549
  }
@@ -726,6 +648,11 @@ export async function prepareAgentRun(agentName, input, params, agentSessionMap,
726
648
  }
727
649
  let messages = [];
728
650
  if (storage) {
651
+ // A tool whose run was interrupted may still be writing its result to this
652
+ // thread. In voice the next turn lands within a second or two, so without
653
+ // this the model would load context that is missing the very thing it is
654
+ // about to be asked about.
655
+ await awaitPendingInterruptNote(threadId);
729
656
  messages = await storage.getMessages(threadId, {
730
657
  lastN: memoryConfig?.lastMessages ?? 20,
731
658
  });
@@ -758,7 +685,6 @@ export async function prepareAgentRun(agentName, input, params, agentSessionMap,
758
685
  instructions = `${instructions}\n\nCurrent context (use these identifiers directly in tool calls — do not ask the user for them):\n${input.context}`;
759
686
  }
760
687
  const resolved = resolveModelConfig(resolvedName, agent);
761
- // Per-request overrides
762
688
  if (input.model) {
763
689
  resolved.model = resolveModelConfig(resolvedName, {
764
690
  ...agent,
@@ -777,6 +703,7 @@ export async function prepareAgentRun(agentName, input, params, agentSessionMap,
777
703
  tools,
778
704
  maxSteps: 1,
779
705
  toolChoice: agent.toolChoice ?? 'auto',
706
+ providerOptions: agent.providerOptions,
780
707
  outputSchema,
781
708
  };
782
709
  return {
@@ -1,10 +1,11 @@
1
1
  import type { CoreAIAgent } from './ai-agent.types.js';
2
2
  import type { AIRunStateService } from '../../services/ai-run-state-service.js';
3
+ import { type RunAIAgentParams } from './ai-agent-prepare.js';
3
4
  export declare const addAIAgent: (agentName: string, agent: CoreAIAgent<any, any>, packageName?: string | null) => void;
4
5
  export declare function approveAIAgent(aiRunState: AIRunStateService, runId: string, approvals: {
5
6
  toolCallId: string;
6
7
  approved: boolean;
7
- }[], expectedAgentName?: string): Promise<{
8
+ }[], expectedAgentName?: string, params?: RunAIAgentParams): Promise<{
8
9
  status: 'resumed' | 'suspended';
9
10
  runId: string;
10
11
  approved: string[];
@@ -1,4 +1,5 @@
1
1
  import { pikkuState } from '../../pikku-state.js';
2
+ import { agentSessionScope, assertAgentAuthorized, assertResourcePrincipalOwner, resolveAgent, } from './ai-agent-prepare.js';
2
3
  export const addAIAgent = (agentName, agent, packageName = null) => {
3
4
  const agentsMeta = pikkuState(packageName, 'agent', 'agentsMeta');
4
5
  const agentMeta = agentsMeta[agentName];
@@ -12,17 +13,20 @@ export const addAIAgent = (agentName, agent, packageName = null) => {
12
13
  }
13
14
  agents.set(agentName, agent);
14
15
  };
15
- export async function approveAIAgent(aiRunState, runId, approvals, expectedAgentName) {
16
+ export async function approveAIAgent(aiRunState, runId, approvals, expectedAgentName, params = {}) {
16
17
  if (!aiRunState)
17
18
  throw new Error('AIRunStateService not available');
18
19
  const run = await aiRunState.getRun(runId);
19
20
  if (!run)
20
21
  throw new Error('Run not found: ' + runId);
22
+ assertResourcePrincipalOwner(params, agentSessionScope(run.agentName), run.resourceId, 'run');
21
23
  if (expectedAgentName && run.agentName !== expectedAgentName) {
22
24
  throw new Error(`Run ${runId} belongs to agent '${run.agentName}', not '${expectedAgentName}'`);
23
25
  }
24
26
  if (run.status !== 'suspended')
25
27
  throw new Error('Run is not suspended: ' + run.status);
28
+ const { agent, packageName } = resolveAgent(run.agentName);
29
+ await assertAgentAuthorized(agent, params, packageName);
26
30
  const approvedIds = new Set(approvals.filter((a) => a.approved).map((a) => a.toolCallId));
27
31
  const rejectedIds = new Set(approvals.filter((a) => !a.approved).map((a) => a.toolCallId));
28
32
  const remaining = (run.pendingApprovals ?? []).filter((p) => !approvedIds.has(p.toolCallId) && !rejectedIds.has(p.toolCallId));
@@ -1,6 +1,7 @@
1
1
  import { saveMessages, resolveMemoryServices, loadContextMessages, trimMessages, getWorkingMemoryMiddleware, } from './ai-agent-memory.js';
2
- import { prepareAgentRun, resolveAgent, buildInstructions, buildToolDefs, resolveOwnerResourceId, agentSessionScope, assertResourceOwner, assertAgentAuthorized, } from './ai-agent-prepare.js';
2
+ import { prepareAgentRun, resolveAgent, buildInstructions, buildToolDefs, resolveOwnerResourceId, agentSessionScope, assertResourcePrincipalOwner, assertAgentAuthorized, } from './ai-agent-prepare.js';
3
3
  import { checkForApprovals, appendStepMessages } from './ai-agent-stream.js';
4
+ import { AgentInterruptedError, isAbortError, persistOrphanedToolResults, registerInterruptibleRun, trackInterruptNote, trackToolExecution, } from './ai-agent-interrupt.js';
4
5
  import { pikkuState, getSingletonServices } from '../../pikku-state.js';
5
6
  import { resolveModelConfig } from './ai-agent-model-config.js';
6
7
  import { AIProviderNotConfiguredError } from '../../errors/errors.js';
@@ -95,6 +96,13 @@ export async function runAIAgent(agentName, input, params, agentSessionMap) {
95
96
  createdAt: new Date(),
96
97
  updatedAt: new Date(),
97
98
  });
99
+ // Registered on the same terms as `streamAIAgent`. A run created here is
100
+ // visible to `interruptAIAgent` through `aiRunState` either way, so skipping
101
+ // this would leave that call finding the run, passing the ownership check and
102
+ // then failing to stop it — reported as if it were running on another host.
103
+ const interruptHandle = registerInterruptibleRun(runId);
104
+ runnerParams.abortSignal = interruptHandle.signal;
105
+ runnerParams.tools = trackToolExecution(runnerParams.tools, interruptHandle);
98
106
  try {
99
107
  const accumulatedSteps = [];
100
108
  const totalUsage = { inputTokens: 0, outputTokens: 0 };
@@ -146,7 +154,7 @@ export async function runAIAgent(agentName, input, params, agentSessionMap) {
146
154
  });
147
155
  if (stepResult.toolCalls.length === 0)
148
156
  break;
149
- const approvalsNeeded = checkForApprovals(stepResult, runnerParams.tools, runId);
157
+ const approvalsNeeded = checkForApprovals(stepResult, runnerParams.tools);
150
158
  if (approvalsNeeded.length > 0) {
151
159
  for (const approval of approvalsNeeded) {
152
160
  const toolDef = runnerParams.tools.find((t) => t.name === approval.toolName);
@@ -154,9 +162,7 @@ export async function runAIAgent(agentName, input, params, agentSessionMap) {
154
162
  try {
155
163
  approval.reason = await toolDef.approvalDescriptionFn(approval.args);
156
164
  }
157
- catch {
158
- // If description generation fails, continue without it
159
- }
165
+ catch { }
160
166
  }
161
167
  }
162
168
  const pendingApprovals = approvalsNeeded.map((a) => a.agentRunId
@@ -255,6 +261,18 @@ export async function runAIAgent(agentName, input, params, agentSessionMap) {
255
261
  };
256
262
  }
257
263
  catch (error) {
264
+ // An interrupt is not a failure, so it skips the `onError` hooks and never
265
+ // becomes an `errorMessage`. Unlike the streaming path there is no partial
266
+ // reply to hand back — nothing was delivered — so the caller gets a typed
267
+ // throw it can tell apart from a provider outage instead of a result.
268
+ const interruption = interruptHandle.interruption;
269
+ if (interruption || isAbortError(error)) {
270
+ await aiRunState.updateRun(runId, { status: 'interrupted' });
271
+ if (storage) {
272
+ trackInterruptNote(threadId, persistOrphanedToolResults(interruptHandle, storage, threadId));
273
+ }
274
+ throw new AgentInterruptedError(runId, interruption ?? { reason: 'user' });
275
+ }
258
276
  for (const mw of aiMiddlewares) {
259
277
  if (mw.onError) {
260
278
  try {
@@ -264,9 +282,7 @@ export async function runAIAgent(agentName, input, params, agentSessionMap) {
264
282
  messages: runnerParams.messages,
265
283
  });
266
284
  }
267
- catch {
268
- // onError hooks must not affect error flow
269
- }
285
+ catch { }
270
286
  }
271
287
  }
272
288
  await aiRunState.updateRun(runId, {
@@ -275,6 +291,9 @@ export async function runAIAgent(agentName, input, params, agentSessionMap) {
275
291
  });
276
292
  throw error;
277
293
  }
294
+ finally {
295
+ interruptHandle.release();
296
+ }
278
297
  }
279
298
  export async function resumeAIAgentSync(runId, approvals, params, expectedAgentName) {
280
299
  const singletonServices = getSingletonServices();
@@ -285,7 +304,7 @@ export async function resumeAIAgentSync(runId, approvals, params, expectedAgentN
285
304
  const run = await aiRunState.getRun(runId);
286
305
  if (!run)
287
306
  throw new Error(`No run found for runId ${runId}`);
288
- assertResourceOwner(resolveOwnerResourceId(params, agentSessionScope(run.agentName), run.resourceId), run.resourceId, 'run');
307
+ assertResourcePrincipalOwner(params, agentSessionScope(run.agentName), run.resourceId, 'run');
289
308
  if (expectedAgentName && run.agentName !== expectedAgentName) {
290
309
  throw new Error(`Run ${runId} belongs to agent '${run.agentName}', not '${expectedAgentName}'`);
291
310
  }
@@ -293,9 +312,6 @@ export async function resumeAIAgentSync(runId, approvals, params, expectedAgentN
293
312
  throw new Error(`Run ${runId} is not suspended (status: ${run.status})`);
294
313
  }
295
314
  const { agent, packageName, resolvedName } = resolveAgent(run.agentName);
296
- // Resuming re-runs the agent, so it re-runs the agent's gate. Run ownership
297
- // alone is not enough: a grant revoked while the run was suspended must stop
298
- // the caller from approving its pending tool calls.
299
315
  await assertAgentAuthorized(agent, params, packageName);
300
316
  const { storage } = resolveMemoryServices(agent, singletonServices);
301
317
  const memoryConfig = agent.memory;
@@ -328,7 +344,6 @@ export async function resumeAIAgentSync(runId, approvals, params, expectedAgentN
328
344
  const rawArgs = typeof pending.args === 'string'
329
345
  ? JSON.parse(pending.args)
330
346
  : pending.args;
331
- // Strip null values recursively — LLMs send null for optional fields but Zod expects undefined
332
347
  const toolArgs = stripNulls(rawArgs) ?? {};
333
348
  try {
334
349
  const toolResult = await matchingTool.execute(toolArgs);
@@ -424,11 +439,18 @@ async function continueAfterToolResultSync(run, agent, packageName, resolvedName
424
439
  tools: resumeTools,
425
440
  maxSteps: 1,
426
441
  toolChoice: (agent.toolChoice ?? 'auto'),
442
+ providerOptions: agent.providerOptions,
427
443
  outputSchema: meta?.outputSchema
428
444
  ? pikkuState(packageName, 'misc', 'schemas').get(meta.outputSchema)
429
445
  : undefined,
430
446
  agentId: run.agentName,
431
447
  };
448
+ // A resumed run keeps its original runId, so the handle registered for the
449
+ // first leg is long gone — an approval that kicks off more generation has to
450
+ // be interruptible on its own terms.
451
+ const interruptHandle = registerInterruptibleRun(run.runId);
452
+ runnerParams.abortSignal = interruptHandle.signal;
453
+ runnerParams.tools = trackToolExecution(runnerParams.tools, interruptHandle);
432
454
  try {
433
455
  const accumulatedSteps = [];
434
456
  const totalUsage = { inputTokens: 0, outputTokens: 0 };
@@ -465,7 +487,7 @@ async function continueAfterToolResultSync(run, agent, packageName, resolvedName
465
487
  });
466
488
  if (stepResult.toolCalls.length === 0)
467
489
  break;
468
- const approvalsNeeded = checkForApprovals(stepResult, runnerParams.tools, run.runId);
490
+ const approvalsNeeded = checkForApprovals(stepResult, runnerParams.tools);
469
491
  if (approvalsNeeded.length > 0) {
470
492
  for (const approval of approvalsNeeded) {
471
493
  const toolDef = runnerParams.tools.find((t) => t.name === approval.toolName);
@@ -473,9 +495,7 @@ async function continueAfterToolResultSync(run, agent, packageName, resolvedName
473
495
  try {
474
496
  approval.reason = await toolDef.approvalDescriptionFn(approval.args);
475
497
  }
476
- catch {
477
- // ignore
478
- }
498
+ catch { }
479
499
  }
480
500
  }
481
501
  const pendingApprovals = approvalsNeeded.map((a) => a.agentRunId
@@ -574,6 +594,14 @@ async function continueAfterToolResultSync(run, agent, packageName, resolvedName
574
594
  };
575
595
  }
576
596
  catch (error) {
597
+ const interruption = interruptHandle.interruption;
598
+ if (interruption || isAbortError(error)) {
599
+ await aiRunState.updateRun(run.runId, { status: 'interrupted' });
600
+ if (storage) {
601
+ trackInterruptNote(run.threadId, persistOrphanedToolResults(interruptHandle, storage, run.threadId));
602
+ }
603
+ throw new AgentInterruptedError(run.runId, interruption ?? { reason: 'user' });
604
+ }
577
605
  for (const mw of aiMiddlewares) {
578
606
  if (mw.onError) {
579
607
  try {
@@ -583,9 +611,7 @@ async function continueAfterToolResultSync(run, agent, packageName, resolvedName
583
611
  messages: runnerParams.messages,
584
612
  });
585
613
  }
586
- catch {
587
- // ignore
588
- }
614
+ catch { }
589
615
  }
590
616
  }
591
617
  await aiRunState.updateRun(run.runId, {
@@ -594,4 +620,7 @@ async function continueAfterToolResultSync(run, agent, packageName, resolvedName
594
620
  });
595
621
  throw error;
596
622
  }
623
+ finally {
624
+ interruptHandle.release();
625
+ }
597
626
  }
@@ -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;