@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
@@ -20,6 +20,7 @@ import { pikkuState, getSingletonServices } from '../../pikku-state.js'
20
20
  import { createMiddlewareSessionWireProps } from '../../services/user-session-service.js'
21
21
  import type { SessionService } from '../../services/user-session-service.js'
22
22
  import { randomUUID } from './ai-agent-utils.js'
23
+ import { awaitPendingInterruptNote } from './ai-agent-interrupt.js'
23
24
  import { streamAIAgent } from './ai-agent-stream.js'
24
25
  import { runAIAgent } from './ai-agent-runner.js'
25
26
  import {
@@ -38,44 +39,38 @@ export type RunAIAgentParams = {
38
39
  sessionService?: SessionService<CoreUserSession>
39
40
  /** Credential accessor for the current request — used to read per-user overrides (e.g. AI_API_KEY). */
40
41
  getCredential?: <T = unknown>(name: string) => T | null | Promise<T | null>
42
+ /** Ephemeral owner identity minted for a sessionless request; never client-supplied, never reused across requests. */
43
+ anonymousOwnerResourceId?: string
41
44
  }
42
45
 
43
- /**
44
- * The ownership key for a thread/run: the trusted principal (the authenticated
45
- * `session.userId` for `'user'` scope, or `session.orgId` for `'org'` scope)
46
- * composed with the client-supplied `resourceId` as a sub-partition —
47
- * `principal:resourceId`. Because the principal is always the prefix, a client
48
- * `resourceId` can sub-divide within the caller's own boundary but can never
49
- * widen access to another user's or org's threads.
50
- *
51
- * Idempotent: a value that is already within the caller's namespace (top-level
52
- * re-entry, sub-agent recursion, or resume, which all pass an already-composite
53
- * `resourceId`) is returned unchanged rather than double-composed.
54
- *
55
- * `'org'` scope with no session org throws {@link ForbiddenError} — falling back
56
- * to a bare/shared key would leak across organizations. Sessionless `'user'`
57
- * wirings have no trusted principal and fall back to the requested `resourceId`
58
- * as a best-effort partition key.
59
- */
60
- export function resolveOwnerResourceId(
46
+ export function resolveSessionPrincipal(
61
47
  params: RunAIAgentParams,
62
- sessionScope: SessionScope | undefined,
63
- requestedResourceId: string
64
- ): string {
48
+ sessionScope: SessionScope | undefined
49
+ ): string | undefined {
65
50
  const session = params.sessionService?.get()
66
- let principal: string | undefined
67
51
  if ((sessionScope ?? 'user') === 'org') {
68
52
  if (!session?.orgId) {
69
53
  throw new ForbiddenError(
70
54
  'This agent is org-scoped but the session has no organization'
71
55
  )
72
56
  }
73
- principal = session.orgId
74
- } else {
75
- principal = session?.userId
57
+ return session.orgId
58
+ }
59
+ return session?.userId
60
+ }
61
+
62
+ export function resolveOwnerResourceId(
63
+ params: RunAIAgentParams,
64
+ sessionScope: SessionScope | undefined,
65
+ requestedResourceId: string
66
+ ): string {
67
+ const principal = resolveSessionPrincipal(params, sessionScope)
68
+
69
+ if (!principal) {
70
+ params.anonymousOwnerResourceId ??= `anon-${randomUUID()}`
71
+ return params.anonymousOwnerResourceId
76
72
  }
77
73
 
78
- if (!principal) return requestedResourceId
79
74
  if (
80
75
  requestedResourceId === principal ||
81
76
  requestedResourceId.startsWith(`${principal}:`)
@@ -85,16 +80,22 @@ export function resolveOwnerResourceId(
85
80
  return `${principal}:${requestedResourceId}`
86
81
  }
87
82
 
88
- /** The declared {@link SessionScope} for an agent, defaulting to `'user'`. */
83
+ export function assertResourcePrincipalOwner(
84
+ params: RunAIAgentParams,
85
+ sessionScope: SessionScope | undefined,
86
+ storedResourceId: string,
87
+ kind: 'thread' | 'run'
88
+ ): void {
89
+ const principal = resolveSessionPrincipal(params, sessionScope)
90
+ if (!principal || !isOwnedByPrincipal(storedResourceId, principal)) {
91
+ throw new ForbiddenError(`Not authorized to access this ${kind}`)
92
+ }
93
+ }
94
+
89
95
  export function agentSessionScope(agentName: string): SessionScope {
90
96
  return resolveAgent(agentName).agent.sessionScope ?? 'user'
91
97
  }
92
98
 
93
- /**
94
- * Enforce that a stored thread/run belongs to the caller's owner resource,
95
- * throwing {@link ForbiddenError} (without echoing the id, to avoid an
96
- * existence oracle) on a mismatch.
97
- */
98
99
  export function assertResourceOwner(
99
100
  ownerResourceId: string,
100
101
  storedResourceId: string,
@@ -105,7 +106,6 @@ export function assertResourceOwner(
105
106
  }
106
107
  }
107
108
 
108
- /** A session's trusted principals, in the order they may be read as. */
109
109
  export function sessionPrincipals(
110
110
  session: { userId?: string; orgId?: string } | undefined
111
111
  ): string[] {
@@ -114,12 +114,6 @@ export function sessionPrincipals(
114
114
  )
115
115
  }
116
116
 
117
- /**
118
- * Whether `storedResourceId` belongs to `principal` under the composition
119
- * {@link resolveOwnerResourceId} performs — either the bare principal or one of
120
- * its `principal:` sub-partitions. The `:` is required so that `alice` does not
121
- * match a `alice-evil:…` lookalike.
122
- */
123
117
  export function isOwnedByPrincipal(
124
118
  storedResourceId: string,
125
119
  principal: string
@@ -130,42 +124,18 @@ export function isOwnedByPrincipal(
130
124
  )
131
125
  }
132
126
 
133
- /**
134
- * The `owners` constraint to pass to `AgentRunService.listThreads` for a caller.
135
- *
136
- * Returns `undefined` — not `[]` — for a session with no principal, because an
137
- * empty list means "match nothing" whereas a sessionless deployment (agent
138
- * `no-auth`) has no ownership model to constrain by. Keeping that carve-out here
139
- * rather than at each call site stops it from being re-derived inconsistently.
140
- */
141
127
  export function threadOwnerConstraint(
142
128
  session: { userId?: string; orgId?: string } | undefined
143
- ): string[] | undefined {
144
- const principals = sessionPrincipals(session)
145
- return principals.length > 0 ? principals : undefined
129
+ ): string[] {
130
+ return sessionPrincipals(session)
146
131
  }
147
132
 
148
- /**
149
- * Whether a stored thread/run may be read by the caller. Shaped as a predicate
150
- * so it can back a `pikkuPermission` — authorization belongs in a function's
151
- * `permissions` field, never in its body.
152
- *
153
- * Unlike {@link assertResourceOwner}, which compares against a single composed
154
- * owner key on the run path, this guards the thread-management reads where the
155
- * caller supplies only a `threadId` — so ownership has to be derived from the
156
- * session rather than from the request.
157
- *
158
- * A session with no principal means the deployment opted out of authorization
159
- * (agent `no-auth`), so there is no ownership model to enforce and access is not
160
- * gated — mirroring {@link resolveOwnerResourceId}'s sessionless fallback to a
161
- * bare resourceId.
162
- */
163
133
  export function canAccessThread(
164
134
  storedResourceId: string,
165
135
  session: { userId?: string; orgId?: string } | undefined
166
136
  ): boolean {
167
137
  const principals = sessionPrincipals(session)
168
- if (principals.length === 0) return true
138
+ if (principals.length === 0) return false
169
139
  return principals.some((principal) =>
170
140
  isOwnedByPrincipal(storedResourceId, principal)
171
141
  )
@@ -173,24 +143,22 @@ export function canAccessThread(
173
143
 
174
144
  export type StreamAIAgentOptions = {
175
145
  requiresToolApproval?: 'all' | 'explicit' | false
176
- /**
177
- * Invoked as soon as the run's AIRunStateService id exists, so transport
178
- * wrappers (e.g. the AG-UI bridge) can stamp the real runId on RUN_STARTED.
179
- */
180
146
  onRunCreated?: (runId: string) => void
181
147
  }
182
148
 
183
- /**
184
- * Non-forgeable brand for the sub-agent approval marker. Only framework code
185
- * (the delegating sub-agent tools below) sets this Symbol on a tool result; a
186
- * sub-agent's LLM-shaped `result.object` — plain JSON — cannot carry a Symbol,
187
- * so `checkForApprovals` trusts the brand rather than the `__approvalRequired`
188
- * string key to decide an approval must be surfaced.
189
- */
190
149
  export const APPROVAL_REQUIRED: unique symbol = Symbol(
191
150
  'pikku.ai.approvalRequired'
192
151
  )
193
152
 
153
+ /**
154
+ * In-process brand proving a credential request was produced by pikku itself and
155
+ * not by tool output an attacker can influence. Never serialized — a value that
156
+ * has crossed a JSON boundary has lost the brand and is treated as untrusted.
157
+ */
158
+ export const CREDENTIAL_REQUIRED: unique symbol = Symbol(
159
+ 'pikku.ai.credentialRequired'
160
+ )
161
+
194
162
  export class ToolApprovalRequired extends PikkuError {
195
163
  public readonly toolCallId: string
196
164
  public readonly toolName: string
@@ -254,10 +222,6 @@ export interface AddonCredentialRequirement {
254
222
  oauth2: boolean
255
223
  }
256
224
 
257
- /**
258
- * Given a list of tool names (e.g. ["oauth-api:getProfile"]),
259
- * returns the wire OAuth credentials required by their addons.
260
- */
261
225
  export function getAddonCredentialRequirements(
262
226
  toolNames: string[]
263
227
  ): AddonCredentialRequirement[] {
@@ -333,26 +297,6 @@ export const resolveAgent = (
333
297
  throw new Error(`AI agent not found: ${agentName}`)
334
298
  }
335
299
 
336
- /**
337
- * Enforces an agent's own authorization before it runs: session presence
338
- * (`auth`), then `scopes`, then `permissions`.
339
- *
340
- * The ordering mirrors the function runner — scopes are an AND gate checked
341
- * first, so they can only ever narrow access, and a missing scope short-circuits
342
- * before any permission function does I/O.
343
- *
344
- * `auth` follows `pikkuSessionlessFunc` rather than `pikkuFunc`: a session is
345
- * required only when `auth: true` is set explicitly. An agent is normally
346
- * reached from a function that has already enforced its own auth, and agents are
347
- * also run from genuinely sessionless contexts (crons, queue workers), so
348
- * requiring a session by default would reject those without adding a meaningful
349
- * gate. `scopes` and `permissions` are always enforced when declared.
350
- *
351
- * Globals are evaluated here too (via {@link runPermissions}) rather than being
352
- * assumed to have already run: an agent is reachable from entry points that do
353
- * not go through the function runner, and re-evaluating an AND gate of
354
- * side-effect-free predicates is idempotent.
355
- */
356
300
  export async function assertAgentAuthorized(
357
301
  agent: CoreAIAgent,
358
302
  params: RunAIAgentParams,
@@ -472,20 +416,10 @@ export function createScopedChannel(
472
416
  setState: (s) => parent.setState(s),
473
417
  getState: () => parent.getState(),
474
418
  clearState: () => parent.clearState(),
419
+ remote: (funcName: string, data?: unknown) => parent.remote(funcName, data),
475
420
  }
476
421
  }
477
422
 
478
- /**
479
- * Build the run input for a delegated sub-agent.
480
- *
481
- * `context` is the PARENT run's identifier block (the "Current context" text
482
- * with organizationId, project/stage ids). A sub-agent's tool-call schema only
483
- * carries { message, session }, so unless the sub-agent inherits the parent's
484
- * context it never sees the authoritative ids — it depends on the model
485
- * re-typing them into `message`, which weak models botch, causing
486
- * schema/permission rejections and retry loops. Forwarding it here is the
487
- * regression this seam guards.
488
- */
489
423
  export function buildSubAgentRunInput(
490
424
  message: string,
491
425
  threadId: string,
@@ -504,13 +438,6 @@ export async function buildToolDefs(
504
438
  streamContext?: StreamContext,
505
439
  aiMiddlewares?: PikkuAIMiddlewareHooks[],
506
440
  agentMode?: 'delegate' | 'supervise',
507
- // The parent run's `context` (the "Current context" identifier block). A
508
- // delegated sub-agent's tool-call input schema only carries { message,
509
- // session }, so without inheriting this the sub-agent never sees the
510
- // authoritative ids (organizationId, project/stage ids) — it depends on the
511
- // model re-typing them into `message`, which weak models botch, causing
512
- // schema/permission rejections and retry loops. Forward it so the sub-agent
513
- // gets the same context block in its instructions.
514
441
  parentContext?: string
515
442
  ): Promise<{ tools: AIAgentToolDef[]; missingRpcs: string[] }> {
516
443
  const singletonServices = getSingletonServices()
@@ -522,7 +449,23 @@ export async function buildToolDefs(
522
449
  const meta = pikkuState(packageName, 'agent', 'agentsMeta')[agentName]
523
450
  if (!meta) return { tools, missingRpcs }
524
451
 
525
- // Get session for permission filtering
452
+ /**
453
+ * A tool's description is what the model is told it does, and the main thing
454
+ * it chooses between tools on. It does not survive into the meta registered at
455
+ * boot: `description` is classed as a verbose field, so the bundled copy has
456
+ * it stripped and `fnMeta.description` is always undefined — every tool was
457
+ * being offered under its own bare name regardless of what its author wrote.
458
+ *
459
+ * `getFunctionsMeta` reads the verbose file and falls back to the minimal one,
460
+ * recovering the authored description wherever the generated `.pikku`
461
+ * directory is readable. Where it is not — no `metaService`, or a deployment
462
+ * shipping only the stripped copy — tools fall back to their name, which is
463
+ * what they did before this lookup existed.
464
+ */
465
+ const describedFunctions = await singletonServices.metaService
466
+ ?.getFunctionsMeta()
467
+ .catch(() => undefined)
468
+
526
469
  const session = params.sessionService
527
470
  ? await params.sessionService.get()
528
471
  : null
@@ -563,10 +506,6 @@ export async function buildToolDefs(
563
506
  continue
564
507
  }
565
508
 
566
- // Filter out tools the user doesn't have auth for. The `pikkuAuth` brand
567
- // only survives on the live permission objects in the function config, so
568
- // the check reads those rather than the metadata (whose by-name registry
569
- // is never populated, which would let every gated tool through).
570
509
  if (fnMeta.permissions?.length) {
571
510
  if (!session) continue
572
511
  const funcConfig = pikkuFuncId
@@ -598,7 +537,6 @@ export async function buildToolDefs(
598
537
  approvalPolicy === 'all' ||
599
538
  (approvalPolicy === 'explicit' && fnMeta?.approvalRequired)
600
539
 
601
- // Build approvalDescriptionFn if the function has an approvalDescription configured
602
540
  let approvalDescriptionFn:
603
541
  | ((input: unknown) => Promise<string>)
604
542
  | undefined
@@ -638,10 +576,14 @@ export async function buildToolDefs(
638
576
 
639
577
  tools.push({
640
578
  name: toolName.replaceAll('@', '_').replaceAll(':', '__'),
641
- description: fnMeta?.description || fnMeta?.title || toolName,
579
+ description:
580
+ describedFunctions?.[pikkuFuncId]?.description ||
581
+ fnMeta?.description ||
582
+ toolName,
642
583
  inputSchema,
643
584
  needsApproval: needsApproval || undefined,
644
585
  approvalDescriptionFn,
586
+ readonly: fnMeta?.readonly || undefined,
645
587
  execute: async (toolInput: unknown) => {
646
588
  const wire: PikkuRawWire = params.sessionService
647
589
  ? { ...createMiddlewareSessionWireProps(params.sessionService) }
@@ -669,8 +611,6 @@ export async function buildToolDefs(
669
611
  continue
670
612
  }
671
613
 
672
- // Filter out sub-agents the user doesn't have auth for, reading the live
673
- // agent config for the same reason the tool path does.
674
614
  if (subMeta.permissions?.length) {
675
615
  if (!session) continue
676
616
  const subAgent = pikkuState(null, 'agent', 'agents').get(subAgentName)
@@ -726,8 +666,6 @@ export async function buildToolDefs(
726
666
  subAgentName,
727
667
  session
728
668
  )
729
- // In supervise mode, suppress sub-agent text from reaching the client.
730
- // Approvals still flow through normally.
731
669
  const effectiveChannel = isDelegate
732
670
  ? subChannel
733
671
  : {
@@ -773,7 +711,6 @@ export async function buildToolDefs(
773
711
  return resultText
774
712
  }
775
713
 
776
- // No stream context: sub-agent runs non-streaming
777
714
  const result = await runAIAgent(
778
715
  subAgentName,
779
716
  buildSubAgentRunInput(message, threadId, resourceId, parentContext),
@@ -863,17 +800,19 @@ export async function buildToolDefs(
863
800
  }
864
801
  }
865
802
 
866
- // A tool's execute() can throw (bad input, RPC failure, DB error, ...). The AI
867
- // SDK catches that at the tool-call boundary and turns it into a conversational
868
- // "tool error" reply — without this, the exception never reaches pikku's own
869
- // logger, so a failing tool is undiagnosable server-side. Log unconditionally,
870
- // even when no aiMiddleware afterToolCall hook is registered to see it.
871
803
  for (const tool of tools) {
872
804
  const originalExecute = tool.execute
873
805
  tool.execute = async (toolInput: unknown) => {
874
806
  try {
875
807
  return await originalExecute(toolInput)
876
- } catch (err) {
808
+ } catch (err: any) {
809
+ if (err?.payload?.error === 'missing_credential') {
810
+ return {
811
+ [CREDENTIAL_REQUIRED]: true,
812
+ __credentialRequired: true,
813
+ ...err.payload,
814
+ }
815
+ }
877
816
  singletonServices.logger.error(
878
817
  `AI agent tool '${tool.name}' threw during execute()`,
879
818
  err
@@ -1001,6 +940,11 @@ export async function prepareAgentRun(
1001
940
 
1002
941
  let messages: AIMessage[] = []
1003
942
  if (storage) {
943
+ // A tool whose run was interrupted may still be writing its result to this
944
+ // thread. In voice the next turn lands within a second or two, so without
945
+ // this the model would load context that is missing the very thing it is
946
+ // about to be asked about.
947
+ await awaitPendingInterruptNote(threadId)
1004
948
  messages = await storage.getMessages(threadId, {
1005
949
  lastN: memoryConfig?.lastMessages ?? 20,
1006
950
  })
@@ -1060,7 +1004,6 @@ export async function prepareAgentRun(
1060
1004
 
1061
1005
  const resolved = resolveModelConfig(resolvedName, agent)
1062
1006
 
1063
- // Per-request overrides
1064
1007
  if (input.model) {
1065
1008
  resolved.model = resolveModelConfig(resolvedName, {
1066
1009
  ...agent,
@@ -1081,6 +1024,7 @@ export async function prepareAgentRun(
1081
1024
  tools,
1082
1025
  maxSteps: 1,
1083
1026
  toolChoice: agent.toolChoice ?? 'auto',
1027
+ providerOptions: agent.providerOptions,
1084
1028
  outputSchema,
1085
1029
  }
1086
1030
 
@@ -1,16 +1,56 @@
1
1
  import { beforeEach, describe, test } from 'node:test'
2
2
  import assert from 'node:assert/strict'
3
3
 
4
- import { resetPikkuState, pikkuState } from '../../pikku-state.js'
4
+ import {
5
+ resetPikkuState,
6
+ pikkuState,
7
+ setSingletonServices,
8
+ } from '../../pikku-state.js'
5
9
  import {
6
10
  addAIAgent,
7
11
  approveAIAgent,
8
12
  getAIAgents,
9
13
  getAIAgentsMeta,
10
14
  } from './ai-agent-registry.js'
15
+ import { clearPermissionsCache } from '../../permissions.js'
16
+ import { ForbiddenError, MissingScopeError } from '../../errors/errors.js'
17
+ import type { CoreAIAgent } from './ai-agent.types.js'
18
+ import type { CoreUserSession } from '../../types/core.types.js'
19
+
20
+ const logger = {
21
+ debug: () => {},
22
+ info: () => {},
23
+ warn: () => {},
24
+ error: () => {},
25
+ } as any
26
+
27
+ const registerAgent = (
28
+ agentName: string,
29
+ overrides: Partial<CoreAIAgent> = {}
30
+ ) => {
31
+ const agent = {
32
+ name: agentName,
33
+ description: `${agentName} description`,
34
+ goal: `${agentName} goal`,
35
+ model: 'test/test-model',
36
+ ...overrides,
37
+ } as CoreAIAgent
38
+ pikkuState(null, 'agent', 'agents').set(agentName, agent)
39
+ pikkuState(null, 'agent', 'agentsMeta')[agentName] = { ...agent } as any
40
+ return agent
41
+ }
42
+
43
+ const sessionService = (session: CoreUserSession | undefined) =>
44
+ ({
45
+ get: () => session,
46
+ setInitial: () => {},
47
+ sessionChanged: false,
48
+ }) as any
11
49
 
12
50
  beforeEach(() => {
13
51
  resetPikkuState()
52
+ clearPermissionsCache()
53
+ setSingletonServices({ logger } as any)
14
54
  })
15
55
 
16
56
  describe('addAIAgent', () => {
@@ -70,7 +110,13 @@ describe('addAIAgent', () => {
70
110
  })
71
111
 
72
112
  describe('approveAIAgent', () => {
113
+ const ownerParams = {
114
+ sessionService: sessionService({ userId: 'resource-1' } as CoreUserSession),
115
+ } as any
116
+
73
117
  test('throws when run state service is missing, run is missing, or run is not suspended', async () => {
118
+ registerAgent('agent')
119
+
74
120
  await assert.rejects(() => approveAIAgent(null as any, 'run-1', []), {
75
121
  message: 'AIRunStateService not available',
76
122
  })
@@ -83,7 +129,9 @@ describe('approveAIAgent', () => {
83
129
  updateRun: async () => {},
84
130
  } as any,
85
131
  'run-1',
86
- []
132
+ [],
133
+ undefined,
134
+ ownerParams
87
135
  ),
88
136
  {
89
137
  message: 'Run not found: run-1',
@@ -111,7 +159,9 @@ describe('approveAIAgent', () => {
111
159
  updateRun: async () => {},
112
160
  } as any,
113
161
  'run-1',
114
- []
162
+ [],
163
+ undefined,
164
+ ownerParams
115
165
  ),
116
166
  {
117
167
  message: 'Run is not suspended: completed',
@@ -120,6 +170,7 @@ describe('approveAIAgent', () => {
120
170
  })
121
171
 
122
172
  test('rejects approval when run agent does not match expected agent', async () => {
173
+ registerAgent('internal-agent')
123
174
  const aiRunState = {
124
175
  getRun: async () => ({
125
176
  runId: 'run-1',
@@ -141,7 +192,8 @@ describe('approveAIAgent', () => {
141
192
  aiRunState,
142
193
  'run-1',
143
194
  [{ toolCallId: 'call-1', approved: true }],
144
- 'public-agent'
195
+ 'public-agent',
196
+ ownerParams
145
197
  ),
146
198
  {
147
199
  message:
@@ -151,6 +203,7 @@ describe('approveAIAgent', () => {
151
203
  })
152
204
 
153
205
  test('marks run resumed when at least one approval is granted', async () => {
206
+ registerAgent('assistant')
154
207
  const updates: any[] = []
155
208
  const result = await approveAIAgent(
156
209
  {
@@ -186,7 +239,9 @@ describe('approveAIAgent', () => {
186
239
  [
187
240
  { toolCallId: 'call-1', approved: true },
188
241
  { toolCallId: 'call-3', approved: false },
189
- ]
242
+ ],
243
+ undefined,
244
+ ownerParams
190
245
  )
191
246
 
192
247
  assert.deepEqual(updates, [
@@ -207,6 +262,7 @@ describe('approveAIAgent', () => {
207
262
  })
208
263
 
209
264
  test('keeps run suspended when nothing is approved', async () => {
265
+ registerAgent('assistant')
210
266
  const updates: any[] = []
211
267
  const result = await approveAIAgent(
212
268
  {
@@ -233,7 +289,9 @@ describe('approveAIAgent', () => {
233
289
  },
234
290
  } as any,
235
291
  'run-3',
236
- [{ toolCallId: 'call-1', approved: false }]
292
+ [{ toolCallId: 'call-1', approved: false }],
293
+ undefined,
294
+ ownerParams
237
295
  )
238
296
 
239
297
  assert.deepEqual(updates, [
@@ -252,6 +310,133 @@ describe('approveAIAgent', () => {
252
310
  })
253
311
  })
254
312
 
313
+ describe('approveAIAgent authorization', () => {
314
+ const suspendedRun = (agentName: string, resourceId: string) => ({
315
+ runId: 'run-auth',
316
+ agentName,
317
+ threadId: 'thread-1',
318
+ resourceId,
319
+ status: 'suspended',
320
+ pendingApprovals: [
321
+ { type: 'tool-call', toolCallId: 'call-1', toolName: 'refund', args: {} },
322
+ ],
323
+ usage: { inputTokens: 0, outputTokens: 0, model: 'test/test-model' },
324
+ createdAt: new Date(),
325
+ updatedAt: new Date(),
326
+ })
327
+
328
+ const runStateFor = (agentName: string, resourceId: string) => {
329
+ const updates: any[] = []
330
+ return {
331
+ updates,
332
+ aiRunState: {
333
+ getRun: async () => suspendedRun(agentName, resourceId),
334
+ updateRun: async (_runId: string, patch: any) => {
335
+ updates.push(patch)
336
+ },
337
+ } as any,
338
+ }
339
+ }
340
+
341
+ test('rejects when the run belongs to another session principal', async () => {
342
+ registerAgent('owned-agent')
343
+ const { updates, aiRunState } = runStateFor('owned-agent', 'user-a:default')
344
+
345
+ await assert.rejects(
346
+ () =>
347
+ approveAIAgent(
348
+ aiRunState,
349
+ 'run-auth',
350
+ [{ toolCallId: 'call-1', approved: true }],
351
+ undefined,
352
+ { sessionService: sessionService({ userId: 'user-b' }) } as any
353
+ ),
354
+ ForbiddenError
355
+ )
356
+ assert.deepEqual(updates, [], 'run state must not be mutated')
357
+ })
358
+
359
+ test('rejects when the agent permissions deny', async () => {
360
+ registerAgent('denied-agent', {
361
+ permissions: { denied: async () => false },
362
+ } as Partial<CoreAIAgent>)
363
+ const { updates, aiRunState } = runStateFor('denied-agent', 'u1')
364
+
365
+ await assert.rejects(
366
+ () =>
367
+ approveAIAgent(
368
+ aiRunState,
369
+ 'run-auth',
370
+ [{ toolCallId: 'call-1', approved: true }],
371
+ undefined,
372
+ { sessionService: sessionService({ userId: 'u1' }) } as any
373
+ ),
374
+ ForbiddenError
375
+ )
376
+ assert.deepEqual(updates, [], 'run state must not be mutated')
377
+ })
378
+
379
+ test('rejects when a required scope is no longer held', async () => {
380
+ registerAgent('scoped-agent', { scopes: ['admin:refund'] })
381
+ const { updates, aiRunState } = runStateFor('scoped-agent', 'u1')
382
+
383
+ await assert.rejects(
384
+ () =>
385
+ approveAIAgent(
386
+ aiRunState,
387
+ 'run-auth',
388
+ [{ toolCallId: 'call-1', approved: true }],
389
+ undefined,
390
+ {
391
+ sessionService: sessionService({
392
+ userId: 'u1',
393
+ scopes: ['support'],
394
+ }),
395
+ } as any
396
+ ),
397
+ MissingScopeError
398
+ )
399
+ assert.deepEqual(updates, [])
400
+ })
401
+
402
+ test('rejects when auth is required and the session is gone', async () => {
403
+ registerAgent('auth-agent', { auth: true })
404
+ const { updates, aiRunState } = runStateFor('auth-agent', 'resource-1')
405
+
406
+ await assert.rejects(
407
+ () =>
408
+ approveAIAgent(aiRunState, 'run-auth', [
409
+ { toolCallId: 'call-1', approved: true },
410
+ ]),
411
+ ForbiddenError
412
+ )
413
+ assert.deepEqual(updates, [])
414
+ })
415
+
416
+ test('allows the owning session through the gate', async () => {
417
+ registerAgent('owned-agent', { scopes: ['admin:refund'] })
418
+ const { updates, aiRunState } = runStateFor('owned-agent', 'user-a:default')
419
+
420
+ const result = await approveAIAgent(
421
+ aiRunState,
422
+ 'run-auth',
423
+ [{ toolCallId: 'call-1', approved: true }],
424
+ undefined,
425
+ {
426
+ sessionService: sessionService({
427
+ userId: 'user-a',
428
+ scopes: ['admin:refund'],
429
+ }),
430
+ } as any
431
+ )
432
+
433
+ assert.equal(result.status, 'resumed')
434
+ assert.deepEqual(updates, [
435
+ { status: 'running', pendingApprovals: undefined },
436
+ ])
437
+ })
438
+ })
439
+
255
440
  describe('getAIAgentsMeta', () => {
256
441
  test('returns the shared metadata registry', () => {
257
442
  const meta = getAIAgentsMeta()