@pikku/core 0.12.72 → 0.12.77

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (848) hide show
  1. package/CHANGELOG.md +1171 -0
  2. package/dist/column-form.d.ts +32 -0
  3. package/dist/column-form.js +42 -0
  4. package/dist/crypto-utils.d.ts +43 -7
  5. package/dist/crypto-utils.js +163 -42
  6. package/dist/data-classification.d.ts +44 -0
  7. package/dist/dev/hot-reload.js +11 -30
  8. package/dist/dev/module-runner.d.ts +3 -7
  9. package/dist/dev/module-runner.js +4 -10
  10. package/dist/dev/reload-meta.d.ts +8 -20
  11. package/dist/dev/reload-meta.js +9 -29
  12. package/dist/errors/error-handler.d.ts +5 -30
  13. package/dist/errors/error-handler.js +16 -32
  14. package/dist/errors/errors.d.ts +32 -151
  15. package/dist/errors/errors.js +55 -157
  16. package/dist/function/abort-scope.d.ts +47 -0
  17. package/dist/function/abort-scope.js +63 -0
  18. package/dist/function/function-runner.js +37 -32
  19. package/dist/function/functions.types.d.ts +57 -136
  20. package/dist/function/functions.types.js +0 -58
  21. package/dist/function/index.d.ts +1 -1
  22. package/dist/function/list.types.d.ts +12 -62
  23. package/dist/function/list.types.js +4 -25
  24. package/dist/handle-error.d.ts +0 -13
  25. package/dist/handle-error.js +0 -18
  26. package/dist/index.d.ts +11 -5
  27. package/dist/index.js +7 -2
  28. package/dist/middleware/auth-apikey.d.ts +3 -18
  29. package/dist/middleware/auth-apikey.js +0 -17
  30. package/dist/middleware/auth-bearer.d.ts +6 -41
  31. package/dist/middleware/auth-bearer.js +5 -41
  32. package/dist/middleware/auth-cookie.d.ts +5 -27
  33. package/dist/middleware/auth-cookie.js +2 -26
  34. package/dist/middleware/cors.d.ts +7 -34
  35. package/dist/middleware/cors.js +7 -34
  36. package/dist/middleware/remote-auth.d.ts +3 -1
  37. package/dist/middleware/remote-auth.js +4 -3
  38. package/dist/middleware/telemetry.d.ts +8 -33
  39. package/dist/middleware/telemetry.js +2 -31
  40. package/dist/middleware-runner.d.ts +4 -55
  41. package/dist/middleware-runner.js +5 -74
  42. package/dist/permissions.d.ts +3 -44
  43. package/dist/permissions.js +19 -71
  44. package/dist/pikku-request.d.ts +0 -6
  45. package/dist/pikku-request.js +0 -6
  46. package/dist/pikku-state.d.ts +0 -26
  47. package/dist/pikku-state.js +2 -30
  48. package/dist/remote.d.ts +3 -5
  49. package/dist/remote.js +9 -8
  50. package/dist/schema.d.ts +5 -39
  51. package/dist/schema.js +5 -39
  52. package/dist/scopes.d.ts +4 -23
  53. package/dist/scopes.js +7 -48
  54. package/dist/secret-value.d.ts +56 -0
  55. package/dist/secret-value.js +46 -0
  56. package/dist/services/ai-agent-runner-service.d.ts +20 -0
  57. package/dist/services/ai-embedding-service.d.ts +2 -25
  58. package/dist/services/audit-service.d.ts +74 -4
  59. package/dist/services/audit-service.js +8 -7
  60. package/dist/services/content-service.d.ts +1 -46
  61. package/dist/services/credential-service.d.ts +3 -40
  62. package/dist/services/credential-wire-service.d.ts +5 -0
  63. package/dist/services/credential-wire-service.js +9 -1
  64. package/dist/services/deployment-service.d.ts +3 -9
  65. package/dist/services/email-service.d.ts +2 -1
  66. package/dist/services/gateway-service.d.ts +0 -15
  67. package/dist/services/http-personas.d.ts +80 -0
  68. package/dist/services/http-personas.js +233 -0
  69. package/dist/services/in-memory-queue-service.d.ts +0 -14
  70. package/dist/services/in-memory-queue-service.js +1 -15
  71. package/dist/services/in-memory-trigger-service.d.ts +0 -18
  72. package/dist/services/in-memory-trigger-service.js +1 -18
  73. package/dist/services/in-memory-workflow-service.d.ts +0 -16
  74. package/dist/services/in-memory-workflow-service.js +4 -33
  75. package/dist/services/index.d.ts +8 -9
  76. package/dist/services/index.js +3 -6
  77. package/dist/services/istanbul-coverage-service.d.ts +1 -5
  78. package/dist/services/istanbul-coverage-service.js +2 -8
  79. package/dist/services/jwt-service.d.ts +1 -16
  80. package/dist/services/local-content-request-handler.d.ts +29 -0
  81. package/dist/services/local-content-request-handler.js +176 -0
  82. package/dist/services/local-content.d.ts +13 -2
  83. package/dist/services/local-content.js +40 -13
  84. package/dist/services/local-gateway-service.d.ts +0 -16
  85. package/dist/services/local-gateway-service.js +2 -17
  86. package/dist/services/local-secrets.d.ts +4 -7
  87. package/dist/services/local-secrets.js +7 -7
  88. package/dist/services/logger-console.d.ts +3 -7
  89. package/dist/services/logger-console.js +3 -7
  90. package/dist/services/logger.d.ts +22 -40
  91. package/dist/services/meta-service.d.ts +23 -26
  92. package/dist/services/meta-service.js +22 -36
  93. package/dist/services/personas-service.d.ts +134 -0
  94. package/dist/services/personas-service.js +40 -0
  95. package/dist/services/pikku-user-id.js +0 -4
  96. package/dist/services/queue-webhook-service.d.ts +2 -36
  97. package/dist/services/queue-webhook-service.js +10 -42
  98. package/dist/services/scheduler-service.d.ts +1 -50
  99. package/dist/services/scheduler-service.js +0 -10
  100. package/dist/services/schema-service.d.ts +1 -24
  101. package/dist/services/scope-service.d.ts +49 -34
  102. package/dist/services/scoped-secret-service.d.ts +4 -7
  103. package/dist/services/scoped-secret-service.js +0 -4
  104. package/dist/services/secret-host-binding.d.ts +8 -0
  105. package/dist/services/secret-host-binding.js +36 -0
  106. package/dist/services/secret-service.d.ts +12 -35
  107. package/dist/services/secretless.d.ts +6 -0
  108. package/dist/services/secretless.js +21 -0
  109. package/dist/services/stub-tracker.d.ts +7 -18
  110. package/dist/services/stub-tracker.js +8 -18
  111. package/dist/services/system-role-guard.d.ts +33 -0
  112. package/dist/services/system-role-guard.js +38 -0
  113. package/dist/services/trigger-service.d.ts +0 -12
  114. package/dist/services/typed-secret-service.d.ts +5 -11
  115. package/dist/services/typed-secret-service.js +1 -7
  116. package/dist/services/v8-coverage-service.d.ts +2 -3
  117. package/dist/services/v8-coverage-service.js +1 -2
  118. package/dist/services/variables-service.d.ts +1 -8
  119. package/dist/services/webhook-service.d.ts +21 -64
  120. package/dist/services/webhook-service.js +6 -20
  121. package/dist/services/workflow-service.d.ts +3 -15
  122. package/dist/testing/service-tests.js +6 -23
  123. package/dist/time-utils.d.ts +0 -16
  124. package/dist/time-utils.js +1 -19
  125. package/dist/types/core.types.d.ts +120 -219
  126. package/dist/types/core.types.js +0 -42
  127. package/dist/types/state.types.d.ts +4 -9
  128. package/dist/utils/hmac.d.ts +4 -10
  129. package/dist/utils/hmac.js +4 -10
  130. package/dist/utils/safe-fetch.d.ts +7 -35
  131. package/dist/utils/safe-fetch.js +13 -53
  132. package/dist/utils.d.ts +1 -6
  133. package/dist/utils.js +6 -15
  134. package/dist/wirings/actor-flow/actor-flow.types.d.ts +1 -34
  135. package/dist/wirings/actor-flow/index.d.ts +0 -9
  136. package/dist/wirings/actor-flow/run-conversation.d.ts +5 -5
  137. package/dist/wirings/actor-flow/run-conversation.js +14 -7
  138. package/dist/wirings/ai-agent/ai-agent-agui.d.ts +0 -5
  139. package/dist/wirings/ai-agent/ai-agent-agui.js +46 -12
  140. package/dist/wirings/ai-agent/ai-agent-helpers.d.ts +7 -0
  141. package/dist/wirings/ai-agent/ai-agent-helpers.js +7 -0
  142. package/dist/wirings/ai-agent/ai-agent-interrupt.d.ts +153 -0
  143. package/dist/wirings/ai-agent/ai-agent-interrupt.js +256 -0
  144. package/dist/wirings/ai-agent/ai-agent-memory.js +0 -2
  145. package/dist/wirings/ai-agent/ai-agent-model-config.d.ts +0 -9
  146. package/dist/wirings/ai-agent/ai-agent-model-config.js +1 -9
  147. package/dist/wirings/ai-agent/ai-agent-prepare.d.ts +10 -99
  148. package/dist/wirings/ai-agent/ai-agent-prepare.js +65 -132
  149. package/dist/wirings/ai-agent/ai-agent-registry.d.ts +2 -1
  150. package/dist/wirings/ai-agent/ai-agent-registry.js +5 -1
  151. package/dist/wirings/ai-agent/ai-agent-runner.js +63 -22
  152. package/dist/wirings/ai-agent/ai-agent-stream.d.ts +25 -2
  153. package/dist/wirings/ai-agent/ai-agent-stream.js +180 -64
  154. package/dist/wirings/ai-agent/ai-agent.types.d.ts +124 -4
  155. package/dist/wirings/ai-agent/index.d.ts +6 -4
  156. package/dist/wirings/ai-agent/index.js +5 -4
  157. package/dist/wirings/ai-agent/voice-input.d.ts +59 -1
  158. package/dist/wirings/ai-agent/voice-input.js +90 -12
  159. package/dist/wirings/ai-agent/voice-output.d.ts +69 -1
  160. package/dist/wirings/ai-agent/voice-output.js +162 -50
  161. package/dist/wirings/channel/channel-common.d.ts +7 -20
  162. package/dist/wirings/channel/channel-common.js +7 -21
  163. package/dist/wirings/channel/channel-handler.js +25 -6
  164. package/dist/wirings/channel/channel-host-rpc.d.ts +25 -0
  165. package/dist/wirings/channel/channel-host-rpc.js +38 -0
  166. package/dist/wirings/channel/channel-middleware-runner.d.ts +0 -12
  167. package/dist/wirings/channel/channel-middleware-runner.js +0 -12
  168. package/dist/wirings/channel/channel-rpc-registry.d.ts +31 -0
  169. package/dist/wirings/channel/channel-rpc-registry.js +89 -0
  170. package/dist/wirings/channel/channel-rpc-responder.d.ts +15 -0
  171. package/dist/wirings/channel/channel-rpc-responder.js +71 -0
  172. package/dist/wirings/channel/channel-rpc-service.d.ts +40 -0
  173. package/dist/wirings/channel/channel-rpc-service.js +106 -0
  174. package/dist/wirings/channel/channel-rpc-validators.d.ts +14 -0
  175. package/dist/wirings/channel/channel-rpc-validators.js +30 -0
  176. package/dist/wirings/channel/channel-rpc.d.ts +5 -0
  177. package/dist/wirings/channel/channel-rpc.js +5 -0
  178. package/dist/wirings/channel/channel-rpc.types.d.ts +90 -0
  179. package/dist/wirings/channel/channel-rpc.types.js +50 -0
  180. package/dist/wirings/channel/channel-runner.d.ts +0 -4
  181. package/dist/wirings/channel/channel-runner.js +0 -14
  182. package/dist/wirings/channel/channel-store.d.ts +0 -10
  183. package/dist/wirings/channel/channel.types.d.ts +12 -1
  184. package/dist/wirings/channel/define-channel-routes.d.ts +0 -20
  185. package/dist/wirings/channel/define-channel-routes.js +0 -20
  186. package/dist/wirings/channel/eventhub-service.d.ts +0 -18
  187. package/dist/wirings/channel/index.d.ts +4 -1
  188. package/dist/wirings/channel/index.js +2 -0
  189. package/dist/wirings/channel/local/local-channel-runner.js +3 -1
  190. package/dist/wirings/channel/local/local-eventhub-service.d.ts +0 -33
  191. package/dist/wirings/channel/local/local-eventhub-service.js +2 -36
  192. package/dist/wirings/channel/log-channels.d.ts +0 -4
  193. package/dist/wirings/channel/log-channels.js +0 -4
  194. package/dist/wirings/channel/pikku-abstract-channel-handler.js +6 -0
  195. package/dist/wirings/channel/serverless/serverless-channel-runner.js +2 -5
  196. package/dist/wirings/cli/channel/cli-approval.d.ts +41 -0
  197. package/dist/wirings/cli/channel/cli-approval.js +81 -0
  198. package/dist/wirings/cli/channel/cli-channel-runner.d.ts +0 -4
  199. package/dist/wirings/cli/channel/cli-channel-runner.js +3 -25
  200. package/dist/wirings/cli/channel/cli-raw-channel-runner.d.ts +47 -9
  201. package/dist/wirings/cli/channel/cli-raw-channel-runner.js +24 -16
  202. package/dist/wirings/cli/channel/cli-raw-client-runner.d.ts +38 -0
  203. package/dist/wirings/cli/channel/cli-raw-client-runner.js +129 -0
  204. package/dist/wirings/cli/channel/index.d.ts +5 -0
  205. package/dist/wirings/cli/channel/index.js +2 -0
  206. package/dist/wirings/cli/cli-runner.d.ts +20 -20
  207. package/dist/wirings/cli/cli-runner.js +28 -89
  208. package/dist/wirings/cli/cli.types.d.ts +14 -3
  209. package/dist/wirings/cli/command-parser.d.ts +1 -10
  210. package/dist/wirings/cli/command-parser.js +10 -87
  211. package/dist/wirings/cli/define-cli-commands.d.ts +1 -17
  212. package/dist/wirings/cli/define-cli-commands.js +1 -17
  213. package/dist/wirings/credential/credential.types.d.ts +0 -12
  214. package/dist/wirings/credential/define-credential.d.ts +48 -0
  215. package/dist/wirings/credential/define-credential.js +47 -0
  216. package/dist/wirings/credential/index.d.ts +1 -1
  217. package/dist/wirings/credential/index.js +1 -1
  218. package/dist/wirings/credential/validate-credential-definitions.d.ts +2 -4
  219. package/dist/wirings/gateway/gateway-runner.d.ts +1 -20
  220. package/dist/wirings/gateway/gateway-runner.js +8 -105
  221. package/dist/wirings/gateway/gateway.types.d.ts +7 -80
  222. package/dist/wirings/http/http-routes.d.ts +0 -63
  223. package/dist/wirings/http/http-routes.js +0 -63
  224. package/dist/wirings/http/http-runner.d.ts +0 -99
  225. package/dist/wirings/http/http-runner.js +9 -165
  226. package/dist/wirings/http/http.types.d.ts +14 -55
  227. package/dist/wirings/http/log-http-routes.d.ts +0 -4
  228. package/dist/wirings/http/log-http-routes.js +0 -4
  229. package/dist/wirings/http/pikku-fetch-http-request.d.ts +0 -40
  230. package/dist/wirings/http/pikku-fetch-http-request.js +0 -58
  231. package/dist/wirings/http/pikku-fetch-http-response.js +0 -3
  232. package/dist/wirings/http/routers/path-to-regex.js +2 -13
  233. package/dist/wirings/http/web-request.d.ts +0 -8
  234. package/dist/wirings/http/web-request.js +25 -17
  235. package/dist/wirings/mcp/mcp-runner.d.ts +1 -4
  236. package/dist/wirings/mcp/mcp-runner.js +1 -14
  237. package/dist/wirings/mcp/mcp.types.d.ts +2 -35
  238. package/dist/wirings/oauth2/oauth2.types.d.ts +0 -28
  239. package/dist/wirings/oauth2/oauth2.types.js +0 -3
  240. package/dist/wirings/persona/define-personas.d.ts +32 -0
  241. package/dist/wirings/persona/define-personas.js +31 -0
  242. package/dist/wirings/persona/index.d.ts +21 -0
  243. package/dist/wirings/persona/index.js +17 -0
  244. package/dist/wirings/persona/persona-email.d.ts +37 -0
  245. package/dist/wirings/persona/persona-email.js +69 -0
  246. package/dist/wirings/persona/persona-environments.d.ts +45 -0
  247. package/dist/wirings/persona/persona-environments.js +81 -0
  248. package/dist/wirings/persona/persona-mailbox.d.ts +101 -0
  249. package/dist/wirings/persona/persona-mailbox.js +53 -0
  250. package/dist/wirings/persona/persona.types.d.ts +136 -0
  251. package/dist/wirings/persona/persona.types.js +1 -0
  252. package/dist/wirings/persona/validate-personas.d.ts +53 -0
  253. package/dist/wirings/persona/validate-personas.js +94 -0
  254. package/dist/wirings/queue/index.d.ts +3 -0
  255. package/dist/wirings/queue/index.js +2 -3
  256. package/dist/wirings/queue/queue-identity.d.ts +28 -0
  257. package/dist/wirings/queue/queue-identity.js +103 -0
  258. package/dist/wirings/queue/queue-runner.d.ts +0 -19
  259. package/dist/wirings/queue/queue-runner.js +9 -30
  260. package/dist/wirings/queue/queue.types.d.ts +20 -90
  261. package/dist/wirings/queue/register-queue-helper.d.ts +0 -12
  262. package/dist/wirings/queue/register-queue-helper.js +0 -11
  263. package/dist/wirings/queue/signed-queue-service.d.ts +17 -0
  264. package/dist/wirings/queue/signed-queue-service.js +42 -0
  265. package/dist/wirings/queue/validate-worker-config.d.ts +2 -23
  266. package/dist/wirings/queue/validate-worker-config.js +0 -14
  267. package/dist/wirings/role/define-system-role.d.ts +32 -0
  268. package/dist/wirings/role/define-system-role.js +31 -0
  269. package/dist/wirings/role/index.d.ts +3 -0
  270. package/dist/wirings/role/index.js +2 -0
  271. package/dist/wirings/role/role.types.d.ts +43 -0
  272. package/dist/wirings/role/role.types.js +1 -0
  273. package/dist/wirings/role/validate-role-definitions.d.ts +21 -0
  274. package/dist/wirings/role/validate-role-definitions.js +71 -0
  275. package/dist/wirings/rpc/addon-runner.d.ts +0 -19
  276. package/dist/wirings/rpc/addon-runner.js +0 -51
  277. package/dist/wirings/rpc/remote-addon-auth.d.ts +3 -13
  278. package/dist/wirings/rpc/remote-addon-auth.js +7 -11
  279. package/dist/wirings/rpc/rpc-runner.d.ts +11 -18
  280. package/dist/wirings/rpc/rpc-runner.js +88 -105
  281. package/dist/wirings/rpc/rpc-types.d.ts +7 -6
  282. package/dist/wirings/rpc/wire-addon.d.ts +25 -0
  283. package/dist/wirings/rpc/wire-addon.js +62 -0
  284. package/dist/wirings/rpc/wire-remote-addon.d.ts +3 -28
  285. package/dist/wirings/rpc/wire-remote-addon.js +0 -8
  286. package/dist/wirings/scheduler/log-schedulers.d.ts +0 -4
  287. package/dist/wirings/scheduler/log-schedulers.js +0 -4
  288. package/dist/wirings/scheduler/scheduler-runner.d.ts +0 -1
  289. package/dist/wirings/scheduler/scheduler-runner.js +0 -1
  290. package/dist/wirings/scheduler/scheduler.types.d.ts +1 -14
  291. package/dist/wirings/scope/define-scope.d.ts +32 -0
  292. package/dist/wirings/scope/define-scope.js +31 -0
  293. package/dist/wirings/scope/index.d.ts +1 -1
  294. package/dist/wirings/scope/index.js +1 -1
  295. package/dist/wirings/scope/scope.types.d.ts +7 -9
  296. package/dist/wirings/scope/validate-scope-definitions.d.ts +2 -21
  297. package/dist/wirings/scope/validate-scope-definitions.js +3 -21
  298. package/dist/wirings/secret/index.d.ts +1 -1
  299. package/dist/wirings/secret/index.js +1 -1
  300. package/dist/wirings/secret/secret.types.d.ts +19 -15
  301. package/dist/wirings/secret/secret.types.js +1 -1
  302. package/dist/wirings/secret/validate-secret-definitions.d.ts +2 -4
  303. package/dist/wirings/trigger/trigger-runner.d.ts +0 -27
  304. package/dist/wirings/trigger/trigger-runner.js +1 -24
  305. package/dist/wirings/trigger/trigger.types.d.ts +1 -82
  306. package/dist/wirings/trigger/trigger.types.js +0 -34
  307. package/dist/wirings/variable/index.d.ts +1 -1
  308. package/dist/wirings/variable/index.js +1 -1
  309. package/dist/wirings/variable/validate-variable-definitions.d.ts +2 -4
  310. package/dist/wirings/variable/variable.types.d.ts +1 -13
  311. package/dist/wirings/variable/variable.types.js +1 -1
  312. package/dist/wirings/virtual-user/index.d.ts +30 -0
  313. package/dist/wirings/virtual-user/index.js +10 -0
  314. package/dist/wirings/virtual-user/prepare-virtual-user-run.d.ts +54 -0
  315. package/dist/wirings/virtual-user/prepare-virtual-user-run.js +49 -0
  316. package/dist/wirings/virtual-user/run-virtual-user.d.ts +92 -0
  317. package/dist/wirings/virtual-user/run-virtual-user.js +478 -0
  318. package/dist/wirings/virtual-user/virtual-user-agents.d.ts +38 -0
  319. package/dist/wirings/virtual-user/virtual-user-agents.js +24 -0
  320. package/dist/wirings/virtual-user/virtual-user-catalogue.d.ts +92 -0
  321. package/dist/wirings/virtual-user/virtual-user-catalogue.js +134 -0
  322. package/dist/wirings/virtual-user/virtual-user-derive.d.ts +26 -0
  323. package/dist/wirings/virtual-user/virtual-user-derive.js +137 -0
  324. package/dist/wirings/virtual-user/virtual-user-dispositions.d.ts +79 -0
  325. package/dist/wirings/virtual-user/virtual-user-dispositions.js +128 -0
  326. package/dist/wirings/virtual-user/virtual-user-intents.d.ts +78 -0
  327. package/dist/wirings/virtual-user/virtual-user-intents.js +142 -0
  328. package/dist/wirings/virtual-user/virtual-user-rng.d.ts +24 -0
  329. package/dist/wirings/virtual-user/virtual-user-rng.js +44 -0
  330. package/dist/wirings/virtual-user/virtual-user-run-store.d.ts +90 -0
  331. package/dist/wirings/virtual-user/virtual-user-run-store.js +1 -0
  332. package/dist/wirings/virtual-user/virtual-user-target.d.ts +21 -0
  333. package/dist/wirings/virtual-user/virtual-user-target.js +34 -0
  334. package/dist/wirings/virtual-user/virtual-user.types.d.ts +199 -0
  335. package/dist/wirings/virtual-user/virtual-user.types.js +8 -0
  336. package/dist/wirings/workflow/dsl/workflow-dsl.types.d.ts +19 -15
  337. package/dist/wirings/workflow/dsl/workflow-runner.d.ts +0 -4
  338. package/dist/wirings/workflow/dsl/workflow-runner.js +0 -4
  339. package/dist/wirings/workflow/feature.d.ts +0 -19
  340. package/dist/wirings/workflow/feature.js +0 -19
  341. package/dist/wirings/workflow/graph/graph-node.d.ts +0 -98
  342. package/dist/wirings/workflow/graph/graph-node.js +0 -34
  343. package/dist/wirings/workflow/graph/graph-runner.js +6 -41
  344. package/dist/wirings/workflow/graph/wire-workflow-graph.d.ts +0 -4
  345. package/dist/wirings/workflow/graph/workflow-graph.types.d.ts +0 -58
  346. package/dist/wirings/workflow/graph/workflow-graph.types.js +0 -6
  347. package/dist/wirings/workflow/index.d.ts +5 -7
  348. package/dist/wirings/workflow/index.js +3 -17
  349. package/dist/wirings/workflow/pikku-scenario-service.d.ts +87 -5
  350. package/dist/wirings/workflow/pikku-scenario-service.js +204 -43
  351. package/dist/wirings/workflow/pikku-workflow-service.d.ts +7 -459
  352. package/dist/wirings/workflow/pikku-workflow-service.js +58 -551
  353. package/dist/wirings/workflow/run-timeline.d.ts +0 -47
  354. package/dist/wirings/workflow/run-timeline.js +0 -22
  355. package/dist/wirings/workflow/scenario-cookie-jar.d.ts +0 -23
  356. package/dist/wirings/workflow/scenario-cookie-jar.js +0 -16
  357. package/dist/wirings/workflow/scenario-poll.d.ts +0 -15
  358. package/dist/wirings/workflow/scenario-poll.js +0 -12
  359. package/dist/wirings/workflow/scenario-prose.d.ts +0 -28
  360. package/dist/wirings/workflow/scenario-prose.js +1 -19
  361. package/dist/wirings/workflow/scenario-step-guards.d.ts +0 -13
  362. package/dist/wirings/workflow/scenario-step-guards.js +1 -14
  363. package/dist/wirings/workflow/scenario-step.types.d.ts +84 -12
  364. package/dist/wirings/workflow/scenario-step.types.js +5 -1
  365. package/dist/wirings/workflow/scenario-surface.d.ts +16 -0
  366. package/dist/wirings/workflow/scenario-surface.js +56 -0
  367. package/dist/wirings/workflow/workflow-invocation-id.d.ts +0 -18
  368. package/dist/wirings/workflow/workflow-invocation-id.js +2 -22
  369. package/dist/wirings/workflow/workflow-queue-workers.d.ts +0 -20
  370. package/dist/wirings/workflow/workflow-queue-workers.js +0 -19
  371. package/dist/wirings/workflow/workflow.types.d.ts +5 -195
  372. package/knowledge/decisions/index.md +19 -0
  373. package/knowledge/decisions/internals/a-secret-that-fails-to-decrypt-fails-the-whole-read.md +49 -0
  374. package/knowledge/decisions/internals/a-virtual-user-run-is-not-a-workflow-and-not-a-queued-job.md +48 -0
  375. package/knowledge/decisions/internals/actor-flow-conversations-seed-a-hidden-kickoff-message.md +23 -0
  376. package/knowledge/decisions/internals/actor-flow-drives-the-target-through-a-transport-seam.md +24 -0
  377. package/knowledge/decisions/internals/actor-flow-verdicts-are-llm-self-evaluations.md +25 -0
  378. package/knowledge/decisions/internals/addon-package-roots-resolve-by-walking-node-module-search-paths.md +26 -0
  379. package/knowledge/decisions/internals/addon-singleton-services-are-cached-per-namespace-not-per-package.md +33 -0
  380. package/knowledge/decisions/internals/addon-workflow-names-are-prefixed-with-the-consumer-namespace.md +28 -0
  381. package/knowledge/decisions/internals/ai-agent-agui-bridge-obeys-the-client-ordering-contract.md +29 -0
  382. package/knowledge/decisions/internals/ai-agent-audio-chunks-carry-the-format-the-provider-returned.md +20 -0
  383. package/knowledge/decisions/internals/ai-agent-credential-suspensions-hide-the-tool-result.md +26 -0
  384. package/knowledge/decisions/internals/ai-agent-delegate-and-supervise-hide-different-text.md +26 -0
  385. package/knowledge/decisions/internals/ai-agent-llm-tool-arguments-have-nulls-stripped.md +23 -0
  386. package/knowledge/decisions/internals/ai-agent-model-config-stays-a-single-resolution-seam.md +25 -0
  387. package/knowledge/decisions/internals/ai-agent-onerror-hooks-cannot-change-the-failure.md +22 -0
  388. package/knowledge/decisions/internals/ai-agent-runner-methods-must-keep-their-receiver.md +22 -0
  389. package/knowledge/decisions/internals/ai-agent-stream-persistence-is-best-effort.md +27 -0
  390. package/knowledge/decisions/internals/ai-agent-sub-agents-inherit-the-parent-context-block.md +26 -0
  391. package/knowledge/decisions/internals/ai-agent-tool-execute-failures-are-logged-unconditionally.md +25 -0
  392. package/knowledge/decisions/internals/ai-agent-voice-input-transcribes-audio-parts-in-place.md +22 -0
  393. package/knowledge/decisions/internals/ai-agent-working-memory-is-persisted-only-when-valid.md +25 -0
  394. package/knowledge/decisions/internals/channel-message-handlers-accept-three-config-shapes.md +30 -0
  395. package/knowledge/decisions/internals/channel-middleware-caches-only-statically-resolved-middleware.md +31 -0
  396. package/knowledge/decisions/internals/channel-state-is-per-socket-session-state-is-per-user.md +29 -0
  397. package/knowledge/decisions/internals/channel-user-id-is-persisted-after-onconnect-middleware-runs.md +28 -0
  398. package/knowledge/decisions/internals/cli-option-names-are-camelcase-in-state-and-kebab-on-the-command-line.md +27 -0
  399. package/knowledge/decisions/internals/cli-parse-errors-are-routed-by-message-prefix.md +28 -0
  400. package/knowledge/decisions/internals/cli-stdout-is-reserved-for-machine-readable-output.md +34 -0
  401. package/knowledge/decisions/internals/cli-unknown-long-options-warn-instead-of-failing.md +29 -0
  402. package/knowledge/decisions/internals/core-column-form-is-an-axis-of-its-own.md +84 -0
  403. package/knowledge/decisions/internals/core-data-classification-brand-is-an-optional-property.md +41 -0
  404. package/knowledge/decisions/internals/core-function-runner-restores-the-wire-fields-it-overwrites.md +44 -0
  405. package/knowledge/decisions/internals/core-hot-reload-merges-generated-meta-never-replaces-it.md +39 -0
  406. package/knowledge/decisions/internals/core-hot-reload-owns-its-module-registry.md +42 -0
  407. package/knowledge/decisions/internals/core-middleware-order-is-scope-then-priority.md +39 -0
  408. package/knowledge/decisions/internals/core-schema-defaults-apply-on-every-transport.md +43 -0
  409. package/knowledge/decisions/internals/core-scopes-are-an-and-gate-separate-from-permissions.md +38 -0
  410. package/knowledge/decisions/internals/core-state-is-a-global-map-written-only-at-registration-time.md +44 -0
  411. package/knowledge/decisions/internals/email-meta-is-read-uncached-because-codegen-rewrites-it-mid-session.md +27 -0
  412. package/knowledge/decisions/internals/gateway-adapters-resolve-lazily-and-are-promise-cached.md +32 -0
  413. package/knowledge/decisions/internals/gateway-webhook-challenges-echo-bytes-not-json.md +28 -0
  414. package/knowledge/decisions/internals/gateway-wiring-is-a-meta-wiring-over-http-and-channels.md +31 -0
  415. package/knowledge/decisions/internals/generated-src-paths-in-pikku-meta-are-absolute.md +26 -0
  416. package/knowledge/decisions/internals/http-request-bodies-are-read-once-and-shared.md +32 -0
  417. package/knowledge/decisions/internals/http-route-groups-cascade-config-in-a-fixed-order.md +28 -0
  418. package/knowledge/decisions/internals/http-router-matches-normalized-paths-but-returns-registered-ones.md +30 -0
  419. package/knowledge/decisions/internals/http-runner-logs-through-a-trace-scoped-logger-functions-do-not.md +26 -0
  420. package/knowledge/decisions/internals/http-set-cookie-headers-are-appended-never-joined.md +28 -0
  421. package/knowledge/decisions/internals/http-sse-streams-flush-headers-only-after-middleware.md +32 -0
  422. package/knowledge/decisions/internals/http-wiring-without-metadata-is-skipped-not-fatal.md +26 -0
  423. package/knowledge/decisions/internals/in-a-scenario-a-4xx-is-data-not-an-exception.md +25 -0
  424. package/knowledge/decisions/internals/in-memory-workflow-history-aliases-the-live-step-object.md +26 -0
  425. package/knowledge/decisions/internals/index.md +117 -0
  426. package/knowledge/decisions/internals/istanbul-statement-counts-attach-to-the-start-line-only.md +25 -0
  427. package/knowledge/decisions/internals/local-trigger-and-gateway-services-assume-a-single-process.md +26 -0
  428. package/knowledge/decisions/internals/node-only-builtins-are-imported-dynamically.md +24 -0
  429. package/knowledge/decisions/internals/one-project-shape-check-two-validators.md +53 -0
  430. package/knowledge/decisions/internals/queue-group-concurrency-keeps-one-shared-queue-fair.md +28 -0
  431. package/knowledge/decisions/internals/queue-jobs-always-carry-an-explicit-attempts-count.md +27 -0
  432. package/knowledge/decisions/internals/remote-addons-dispatch-over-http-instead-of-local-meta.md +31 -0
  433. package/knowledge/decisions/internals/rpc-names-resolve-through-package-scope-before-root.md +32 -0
  434. package/knowledge/decisions/internals/scenario-agent-calls-sign-in-on-401-only.md +27 -0
  435. package/knowledge/decisions/internals/scenario-meta-lives-apart-from-app-meta-but-merges-when-read-off-disk.md +26 -0
  436. package/knowledge/decisions/internals/scenario-steps-return-drained-response-records.md +27 -0
  437. package/knowledge/decisions/internals/scenarios-live-in-files-named-for-them.md +48 -0
  438. package/knowledge/decisions/internals/scope-roots-may-be-co-declared-by-an-addon-and-its-host-app.md +30 -0
  439. package/knowledge/decisions/internals/serverless-channel-disconnect-must-tolerate-a-missing-channel.md +28 -0
  440. package/knowledge/decisions/internals/the-dev-queue-copies-prod-timing-and-serialization-semantics.md +30 -0
  441. package/knowledge/decisions/internals/the-embedding-model-is-pinned-per-service-and-doc-query-embedding-is-split.md +29 -0
  442. package/knowledge/decisions/internals/the-in-memory-workflow-service-is-inline-only-and-single-process.md +27 -0
  443. package/knowledge/decisions/internals/the-kek-salt-is-scoped-to-the-key-version.md +40 -0
  444. package/knowledge/decisions/internals/the-schema-service-is-never-stubbed.md +26 -0
  445. package/knowledge/decisions/internals/trigger-declaration-is-split-from-trigger-source.md +33 -0
  446. package/knowledge/decisions/internals/typed-secret-service-caches-for-the-process-lifetime.md +26 -0
  447. package/knowledge/decisions/internals/validate-checks-personas-through-a-shared-module.md +43 -0
  448. package/knowledge/decisions/internals/webhook-delivery-history-records-every-attempt-best-effort.md +26 -0
  449. package/knowledge/decisions/internals/webhook-service-collaborators-are-constructor-args-not-locator-lookups.md +25 -0
  450. package/knowledge/decisions/internals/whether-a-run-is-inline-is-read-from-the-run-record.md +58 -0
  451. package/knowledge/decisions/internals/workflow-approval-expiry-is-decided-from-a-recorded-deadline.md +34 -0
  452. package/knowledge/decisions/internals/workflow-core-never-imports-a-browser-driver.md +42 -0
  453. package/knowledge/decisions/internals/workflow-dsl-meta-separates-runtime-expressions-from-literals.md +38 -0
  454. package/knowledge/decisions/internals/workflow-features-resolve-scenarios-by-object-identity.md +29 -0
  455. package/knowledge/decisions/internals/workflow-graph-inline-and-queued-runs-share-one-planner.md +42 -0
  456. package/knowledge/decisions/internals/workflow-graph-node-notes-are-excluded-from-the-graph-hash.md +25 -0
  457. package/knowledge/decisions/internals/workflow-inline-runs-report-their-run-id-before-they-can-fail.md +29 -0
  458. package/knowledge/decisions/internals/workflow-invocation-id-is-the-dedupe-key-not-step-id.md +43 -0
  459. package/knowledge/decisions/internals/workflow-queued-step-dispatch-requires-an-explicit-opt-in.md +29 -0
  460. package/knowledge/decisions/internals/workflow-queues-are-per-workflow-by-default.md +42 -0
  461. package/knowledge/decisions/internals/workflow-repeated-step-names-get-an-ordinal-suffix.md +33 -0
  462. package/knowledge/decisions/internals/workflow-replay-reads-its-steps-once-and-caches-only-the-immutable-half.md +32 -0
  463. package/knowledge/decisions/internals/workflow-retries-are-owned-by-the-workflow-not-the-queue.md +31 -0
  464. package/knowledge/decisions/internals/workflow-run-capabilities-are-extensions-not-subclasses.md +39 -0
  465. package/knowledge/decisions/internals/workflow-run-mirror-is-never-a-source-of-truth.md +29 -0
  466. package/knowledge/decisions/internals/workflow-run-polling-backs-off-to-the-callers-ceiling.md +33 -0
  467. package/knowledge/decisions/internals/workflow-run-timeline-is-a-pure-fold-over-durable-history.md +37 -0
  468. package/knowledge/decisions/internals/workflow-scenario-assertions-never-retry-and-record-one-step.md +50 -0
  469. package/knowledge/decisions/internals/workflow-scenario-hooks-are-a-scenario-only-affordance.md +43 -0
  470. package/knowledge/decisions/internals/workflow-scenario-prose-is-rendered-from-typed-calls-not-parsed-from-english.md +32 -0
  471. package/knowledge/decisions/internals/workflow-scenario-quarantine-reason-lives-in-code.md +18 -0
  472. package/knowledge/decisions/internals/workflow-scenario-step-targets-are-string-literals-for-the-inspector.md +34 -0
  473. package/knowledge/decisions/internals/workflow-step-compensation-runs-as-its-own-durable-step.md +26 -0
  474. package/knowledge/decisions/internals/workflow-step-dispatch-failure-is-transient-not-a-run-failure.md +33 -0
  475. package/knowledge/decisions/internals/workflow-step-lock-is-held-only-to-claim-the-step.md +27 -0
  476. package/knowledge/decisions/internals/workflow-step-rpc-name-is-provenance-only.md +34 -0
  477. package/knowledge/decisions/internals/workflow-suspend-and-approval-reasons-are-durable-step-identities.md +38 -0
  478. package/knowledge/decisions/internals/workflow-suspended-runs-keep-their-in-process-context.md +30 -0
  479. package/knowledge/decisions/security/a-dropped-audit-write-is-always-logged.md +26 -0
  480. package/knowledge/decisions/security/actor-flow-missing-approval-decisions-default-to-denied.md +22 -0
  481. package/knowledge/decisions/security/actor-sign-in-is-proven-by-set-cookie-not-a-non-empty-jar.md +27 -0
  482. package/knowledge/decisions/security/actor-sign-in-only-works-for-actor-flagged-users.md +27 -0
  483. package/knowledge/decisions/security/addon-auth-and-tags-only-tighten.md +43 -0
  484. package/knowledge/decisions/security/addon-config-gates-apply-only-at-the-namespaced-rpc-boundary.md +52 -0
  485. package/knowledge/decisions/security/addon-scopes-are-resolved-where-the-function-runs.md +46 -0
  486. package/knowledge/decisions/security/ai-agent-approval-forwarding-requires-a-symbol-brand.md +27 -0
  487. package/knowledge/decisions/security/ai-agent-credential-requests-are-symbol-branded.md +37 -0
  488. package/knowledge/decisions/security/ai-agent-gate-requires-a-session-only-when-auth-is-true.md +31 -0
  489. package/knowledge/decisions/security/ai-agent-ownership-failures-never-echo-the-resource.md +23 -0
  490. package/knowledge/decisions/security/ai-agent-resume-re-runs-the-authorization-gate.md +22 -0
  491. package/knowledge/decisions/security/ai-agent-sessionless-deployments-have-no-thread-ownership.md +39 -0
  492. package/knowledge/decisions/security/ai-agent-thread-ownership-composes-the-session-principal.md +30 -0
  493. package/knowledge/decisions/security/ai-agent-tool-filtering-reads-the-live-function-config.md +24 -0
  494. package/knowledge/decisions/security/an-empty-owners-constraint-matches-nothing.md +30 -0
  495. package/knowledge/decisions/security/an-exposed-ungated-function-is-a-codegen-warning.md +49 -0
  496. package/knowledge/decisions/security/console-addon-privileged-functions-gate-themselves.md +76 -0
  497. package/knowledge/decisions/security/core-safe-fetch-blocks-ssrf-by-host-literal-not-dns.md +39 -0
  498. package/knowledge/decisions/security/core-secrets-use-a-per-secret-dek-wrapped-by-a-kek.md +37 -0
  499. package/knowledge/decisions/security/gateway-handlers-run-through-the-function-runner-gate.md +31 -0
  500. package/knowledge/decisions/security/gateway-middleware-sessions-must-be-bridged-onto-the-wire.md +30 -0
  501. package/knowledge/decisions/security/global-permissions-and-function-permissions-are-independent-gates.md +40 -0
  502. package/knowledge/decisions/security/http-error-detail-is-withheld-from-clients-in-production.md +33 -0
  503. package/knowledge/decisions/security/http-request-bodies-are-bounded-before-they-are-buffered.md +46 -0
  504. package/knowledge/decisions/security/index.md +55 -0
  505. package/knowledge/decisions/security/mcp-internal-error-details-are-double-gated-on-production.md +27 -0
  506. package/knowledge/decisions/security/passphrases-are-stretched-key-material-is-expanded.md +40 -0
  507. package/knowledge/decisions/security/permission-auth-filtering-requires-live-permission-functions.md +31 -0
  508. package/knowledge/decisions/security/pikku-carries-actor-scopes-as-data-and-the-app-grants-them.md +26 -0
  509. package/knowledge/decisions/security/queue-job-identities-are-signed-at-enqueue.md +69 -0
  510. package/knowledge/decisions/security/queue-jobs-carry-the-producers-pikku-user-id.md +39 -0
  511. package/knowledge/decisions/security/remote-addon-tokens-are-client-credentials-not-mesh-trust.md +34 -0
  512. package/knowledge/decisions/security/scaffold-features-are-authenticated-unless-opted-out.md +49 -0
  513. package/knowledge/decisions/security/scenario-step-functions-are-never-externally-invocable.md +30 -0
  514. package/knowledge/decisions/security/scope-resolution-happens-at-the-session-boundary-and-sync-never-deletes.md +28 -0
  515. package/knowledge/decisions/security/self-authentication-is-declared-not-detected.md +34 -0
  516. package/knowledge/decisions/security/signed-content-urls-bind-the-request-path.md +37 -0
  517. package/knowledge/decisions/security/webhook-bodies-are-signed-before-they-are-enqueued.md +25 -0
  518. package/knowledge/decisions/security/workflow-actor-steps-always-use-the-real-transport.md +34 -0
  519. package/knowledge/decisions/security/workflow-approval-payloads-are-validated-on-replay-inside-the-workflow.md +40 -0
  520. package/knowledge/decisions/security/workflow-queued-steps-rehydrate-their-session-from-the-run-wire.md +32 -0
  521. package/knowledge/decisions/security/workflow-scenario-sessions-are-isolated-per-actor-and-per-scenario.md +32 -0
  522. package/knowledge/decisions/security/workflow-scenario-steps-are-never-network-invocable.md +31 -0
  523. package/knowledge/index.md +24 -0
  524. package/knowledge/questions/index.md +15 -0
  525. package/package.json +6 -2
  526. package/run-tests.sh +0 -0
  527. package/src/column-form.test.ts +97 -0
  528. package/src/column-form.ts +58 -0
  529. package/src/crypto-utils.test.ts +460 -19
  530. package/src/crypto-utils.ts +306 -59
  531. package/src/data-classification.ts +45 -7
  532. package/src/dev/hot-reload.test.ts +0 -4
  533. package/src/dev/hot-reload.ts +11 -30
  534. package/src/dev/module-runner.ts +7 -32
  535. package/src/dev/reload-meta.ts +9 -29
  536. package/src/errors/error-handler.ts +20 -35
  537. package/src/errors/error.test.ts +30 -1
  538. package/src/errors/errors.ts +73 -157
  539. package/src/function/abort-scope.test.ts +97 -0
  540. package/src/function/abort-scope.ts +80 -0
  541. package/src/function/function-runner.test.ts +0 -7
  542. package/src/function/function-runner.ts +62 -32
  543. package/src/function/functions.types.ts +95 -138
  544. package/src/function/index.ts +1 -0
  545. package/src/function/list.types.test.ts +3 -25
  546. package/src/function/list.types.ts +12 -62
  547. package/src/handle-error.ts +0 -18
  548. package/src/index.ts +84 -3
  549. package/src/middleware/auth-apikey.test.ts +0 -1
  550. package/src/middleware/auth-apikey.ts +0 -17
  551. package/src/middleware/auth-bearer.test.ts +3 -5
  552. package/src/middleware/auth-bearer.ts +5 -41
  553. package/src/middleware/auth-cookie.test.ts +0 -6
  554. package/src/middleware/auth-cookie.ts +2 -26
  555. package/src/middleware/cors.test.ts +34 -0
  556. package/src/middleware/cors.ts +12 -33
  557. package/src/middleware/remote-auth.test.ts +26 -10
  558. package/src/middleware/remote-auth.ts +11 -3
  559. package/src/middleware/telemetry.ts +2 -31
  560. package/src/middleware-runner.test.ts +0 -2
  561. package/src/middleware-runner.ts +5 -74
  562. package/src/permissions.test.ts +30 -0
  563. package/src/permissions.ts +24 -74
  564. package/src/pikku-request.ts +0 -6
  565. package/src/pikku-state.ts +2 -30
  566. package/src/production-barrels-stay-lean.test.ts +110 -0
  567. package/src/remote.test.ts +173 -0
  568. package/src/remote.ts +18 -8
  569. package/src/schema.ts +5 -39
  570. package/src/scopes.ts +7 -48
  571. package/src/secret-value.test.ts +204 -0
  572. package/src/secret-value.ts +111 -0
  573. package/src/services/ai-agent-runner-service.ts +20 -0
  574. package/src/services/ai-embedding-service.ts +3 -25
  575. package/src/services/audit-service.ts +88 -11
  576. package/src/services/content-service.ts +1 -46
  577. package/src/services/credential-service.ts +3 -40
  578. package/src/services/credential-wire-service.test.ts +0 -2
  579. package/src/services/credential-wire-service.ts +9 -1
  580. package/src/services/deployment-service.ts +3 -9
  581. package/src/services/email-service.ts +3 -1
  582. package/src/services/gateway-service.ts +0 -15
  583. package/src/services/{http-scenario-actors-converse.test.ts → http-personas-converse.test.ts} +38 -9
  584. package/src/services/{http-scenario-actors.test.ts → http-personas.test.ts} +39 -22
  585. package/src/services/{http-scenario-actors.ts → http-personas.ts} +85 -45
  586. package/src/services/in-memory-queue-service.ts +1 -15
  587. package/src/services/in-memory-trigger-service.ts +1 -18
  588. package/src/services/in-memory-workflow-service.test.ts +0 -13
  589. package/src/services/in-memory-workflow-service.ts +4 -38
  590. package/src/services/index.ts +23 -18
  591. package/src/services/istanbul-coverage-service.ts +2 -8
  592. package/src/services/jwt-service.ts +1 -16
  593. package/src/services/local-content-request-handler.test.ts +202 -0
  594. package/src/services/local-content-request-handler.ts +267 -0
  595. package/src/services/local-content.test.ts +159 -27
  596. package/src/services/local-content.ts +55 -23
  597. package/src/services/local-gateway-service.ts +2 -17
  598. package/src/services/local-secrets.test.ts +20 -5
  599. package/src/services/local-secrets.ts +15 -11
  600. package/src/services/logger-console.test.ts +0 -1
  601. package/src/services/logger-console.ts +3 -7
  602. package/src/services/logger.ts +31 -46
  603. package/src/services/meta-service.test.ts +1 -5
  604. package/src/services/meta-service.ts +41 -61
  605. package/src/services/{scenario-actors-service.ts → personas-service.ts} +48 -43
  606. package/src/services/pikku-user-id.ts +0 -4
  607. package/src/services/queue-webhook-service.test.ts +2 -1
  608. package/src/services/queue-webhook-service.ts +10 -42
  609. package/src/services/scheduler-service.ts +1 -50
  610. package/src/services/schema-service.ts +1 -24
  611. package/src/services/scope-service.ts +50 -34
  612. package/src/services/scoped-secret-service.ts +4 -7
  613. package/src/services/secret-host-binding.test.ts +138 -0
  614. package/src/services/secret-host-binding.ts +51 -0
  615. package/src/services/secret-service.ts +12 -35
  616. package/src/services/secretless.test.ts +54 -0
  617. package/src/services/secretless.ts +29 -0
  618. package/src/services/stub-tracker.ts +8 -18
  619. package/src/services/system-role-guard.test.ts +93 -0
  620. package/src/services/system-role-guard.ts +71 -0
  621. package/src/services/trigger-service.ts +0 -12
  622. package/src/services/typed-secret-service.ts +12 -14
  623. package/src/services/v8-coverage-service.ts +3 -6
  624. package/src/services/variables-service.ts +1 -8
  625. package/src/services/webhook-service.ts +23 -64
  626. package/src/services/workflow-service.ts +3 -20
  627. package/src/testing/service-tests.ts +6 -32
  628. package/src/time-utils.ts +1 -19
  629. package/src/types/core.types.ts +137 -229
  630. package/src/types/state.types.ts +7 -9
  631. package/src/utils/hmac.ts +4 -10
  632. package/src/utils/safe-fetch.ts +13 -54
  633. package/src/utils.test.ts +11 -2
  634. package/src/utils.ts +6 -15
  635. package/src/wirings/actor-flow/actor-flow.types.ts +1 -34
  636. package/src/wirings/actor-flow/index.ts +0 -9
  637. package/src/wirings/actor-flow/run-conversation.test.ts +11 -6
  638. package/src/wirings/actor-flow/run-conversation.ts +19 -12
  639. package/src/wirings/ai-agent/ai-agent-agui.test.ts +91 -10
  640. package/src/wirings/ai-agent/ai-agent-agui.ts +49 -17
  641. package/src/wirings/ai-agent/ai-agent-helpers.ts +20 -0
  642. package/src/wirings/ai-agent/ai-agent-interrupt.test.ts +842 -0
  643. package/src/wirings/ai-agent/ai-agent-interrupt.ts +399 -0
  644. package/src/wirings/ai-agent/ai-agent-memory.ts +0 -2
  645. package/src/wirings/ai-agent/ai-agent-model-config.ts +1 -9
  646. package/src/wirings/ai-agent/ai-agent-prepare.test.ts +202 -31
  647. package/src/wirings/ai-agent/ai-agent-prepare.ts +89 -139
  648. package/src/wirings/ai-agent/ai-agent-registry.test.ts +191 -6
  649. package/src/wirings/ai-agent/ai-agent-registry.ts +18 -1
  650. package/src/wirings/ai-agent/ai-agent-resume-authorization.test.ts +0 -2
  651. package/src/wirings/ai-agent/ai-agent-runner.test.ts +11 -9
  652. package/src/wirings/ai-agent/ai-agent-runner.ts +85 -35
  653. package/src/wirings/ai-agent/ai-agent-stream.test.ts +205 -103
  654. package/src/wirings/ai-agent/ai-agent-stream.ts +224 -76
  655. package/src/wirings/ai-agent/ai-agent-thread-ownership.test.ts +301 -0
  656. package/src/wirings/ai-agent/ai-agent.types.ts +130 -5
  657. package/src/wirings/ai-agent/index.ts +37 -3
  658. package/src/wirings/ai-agent/voice-input.test.ts +137 -7
  659. package/src/wirings/ai-agent/voice-input.ts +96 -12
  660. package/src/wirings/ai-agent/voice-output.test.ts +512 -0
  661. package/src/wirings/ai-agent/voice-output.ts +243 -56
  662. package/src/wirings/channel/channel-common.ts +15 -20
  663. package/src/wirings/channel/channel-handler.test.ts +50 -0
  664. package/src/wirings/channel/channel-handler.ts +32 -11
  665. package/src/wirings/channel/channel-host-rpc.test.ts +150 -0
  666. package/src/wirings/channel/channel-host-rpc.ts +69 -0
  667. package/src/wirings/channel/channel-middleware-runner.test.ts +0 -1
  668. package/src/wirings/channel/channel-middleware-runner.ts +0 -12
  669. package/src/wirings/channel/channel-rpc-registry.ts +116 -0
  670. package/src/wirings/channel/channel-rpc-responder.ts +117 -0
  671. package/src/wirings/channel/channel-rpc-service.ts +146 -0
  672. package/src/wirings/channel/channel-rpc-validators.ts +65 -0
  673. package/src/wirings/channel/channel-rpc.test.ts +820 -0
  674. package/src/wirings/channel/channel-rpc.ts +5 -0
  675. package/src/wirings/channel/channel-rpc.types.ts +150 -0
  676. package/src/wirings/channel/channel-runner.ts +0 -14
  677. package/src/wirings/channel/channel-store.ts +0 -10
  678. package/src/wirings/channel/channel.types.ts +19 -8
  679. package/src/wirings/channel/define-channel-routes.ts +0 -20
  680. package/src/wirings/channel/eventhub-service.ts +0 -18
  681. package/src/wirings/channel/index.ts +35 -0
  682. package/src/wirings/channel/local/local-channel-handler.ts +3 -1
  683. package/src/wirings/channel/local/local-channel-runner.test.ts +0 -10
  684. package/src/wirings/channel/local/local-channel-runner.ts +3 -1
  685. package/src/wirings/channel/local/local-eventhub-service.test.ts +0 -13
  686. package/src/wirings/channel/local/local-eventhub-service.ts +2 -37
  687. package/src/wirings/channel/log-channels.ts +0 -4
  688. package/src/wirings/channel/pikku-abstract-channel-handler.test.ts +83 -2
  689. package/src/wirings/channel/pikku-abstract-channel-handler.ts +7 -0
  690. package/src/wirings/channel/serverless/serverless-channel-runner.ts +2 -5
  691. package/src/wirings/cli/channel/cli-approval.test.ts +177 -0
  692. package/src/wirings/cli/channel/cli-approval.ts +135 -0
  693. package/src/wirings/cli/channel/cli-channel-runner.ts +4 -26
  694. package/src/wirings/cli/channel/cli-raw-channel-runner.test.ts +169 -0
  695. package/src/wirings/cli/channel/cli-raw-channel-runner.ts +59 -16
  696. package/src/wirings/cli/channel/cli-raw-client-runner.test.ts +480 -0
  697. package/src/wirings/cli/channel/cli-raw-client-runner.ts +185 -0
  698. package/src/wirings/cli/channel/index.ts +13 -0
  699. package/src/wirings/cli/cli-runner.test.ts +0 -1
  700. package/src/wirings/cli/cli-runner.ts +46 -88
  701. package/src/wirings/cli/cli.types.ts +14 -3
  702. package/src/wirings/cli/command-parser.test.ts +0 -4
  703. package/src/wirings/cli/command-parser.ts +11 -91
  704. package/src/wirings/cli/define-cli-commands.ts +1 -17
  705. package/src/wirings/credential/credential.types.ts +0 -12
  706. package/src/wirings/credential/{wire-credential.ts → define-credential.ts} +7 -7
  707. package/src/wirings/credential/index.ts +1 -1
  708. package/src/wirings/credential/validate-credential-definitions.ts +2 -4
  709. package/src/wirings/gateway/gateway-runner.test.ts +1 -21
  710. package/src/wirings/gateway/gateway-runner.ts +8 -110
  711. package/src/wirings/gateway/gateway.types.ts +7 -80
  712. package/src/wirings/http/http-routes.test.ts +0 -3
  713. package/src/wirings/http/http-routes.ts +0 -86
  714. package/src/wirings/http/http-runner.test.ts +0 -1
  715. package/src/wirings/http/http-runner.ts +8 -167
  716. package/src/wirings/http/http.types.ts +15 -62
  717. package/src/wirings/http/log-http-routes.ts +0 -4
  718. package/src/wirings/http/pikku-fetch-http-request.test.ts +2 -10
  719. package/src/wirings/http/pikku-fetch-http-request.ts +0 -58
  720. package/src/wirings/http/pikku-fetch-http-response.test.ts +1 -1
  721. package/src/wirings/http/pikku-fetch-http-response.ts +0 -3
  722. package/src/wirings/http/routers/path-to-regex.test.ts +4 -17
  723. package/src/wirings/http/routers/path-to-regex.ts +2 -13
  724. package/src/wirings/http/web-request.test.ts +33 -2
  725. package/src/wirings/http/web-request.ts +30 -17
  726. package/src/wirings/mcp/mcp-endpoint-registry.test.ts +0 -1
  727. package/src/wirings/mcp/mcp-runner.ts +2 -17
  728. package/src/wirings/mcp/mcp.types.ts +7 -42
  729. package/src/wirings/oauth2/oauth2.types.ts +0 -30
  730. package/src/wirings/persona/define-personas.ts +33 -0
  731. package/src/wirings/persona/index.ts +62 -0
  732. package/src/wirings/persona/persona-email.ts +87 -0
  733. package/src/wirings/persona/persona-environments.test.ts +183 -0
  734. package/src/wirings/persona/persona-environments.ts +138 -0
  735. package/src/wirings/persona/persona-mailbox.ts +156 -0
  736. package/src/wirings/persona/persona.test.ts +220 -0
  737. package/src/wirings/persona/persona.types.ts +142 -0
  738. package/src/wirings/persona/validate-personas.ts +133 -0
  739. package/src/wirings/queue/index.ts +13 -3
  740. package/src/wirings/queue/queue-identity.test.ts +454 -0
  741. package/src/wirings/queue/queue-identity.ts +176 -0
  742. package/src/wirings/queue/queue-runner.ts +12 -31
  743. package/src/wirings/queue/queue.types.ts +25 -90
  744. package/src/wirings/queue/register-queue-helper.ts +0 -14
  745. package/src/wirings/queue/signed-queue-service.ts +60 -0
  746. package/src/wirings/queue/validate-worker-config.ts +2 -28
  747. package/src/wirings/role/define-system-role.ts +33 -0
  748. package/src/wirings/role/index.ts +13 -0
  749. package/src/wirings/role/role.test.ts +104 -0
  750. package/src/wirings/role/role.types.ts +47 -0
  751. package/src/wirings/role/validate-role-definitions.ts +93 -0
  752. package/src/wirings/rpc/addon-auth-tags.test.ts +223 -0
  753. package/src/wirings/rpc/addon-runner.ts +0 -56
  754. package/src/wirings/rpc/addon-scopes.test.ts +225 -0
  755. package/src/wirings/rpc/remote-addon-auth.ts +9 -16
  756. package/src/wirings/rpc/rpc-runner.test.ts +192 -6
  757. package/src/wirings/rpc/rpc-runner.ts +145 -127
  758. package/src/wirings/rpc/rpc-types.ts +11 -6
  759. package/src/wirings/rpc/wire-addon.test.ts +43 -1
  760. package/src/wirings/rpc/wire-addon.ts +99 -0
  761. package/src/wirings/rpc/wire-remote-addon.ts +9 -29
  762. package/src/wirings/scheduler/log-schedulers.ts +0 -4
  763. package/src/wirings/scheduler/scheduler-runner.test.ts +1 -8
  764. package/src/wirings/scheduler/scheduler-runner.ts +0 -2
  765. package/src/wirings/scheduler/scheduler.types.ts +1 -14
  766. package/src/wirings/scope/{wire-scope.ts → define-scope.ts} +5 -6
  767. package/src/wirings/scope/index.ts +1 -1
  768. package/src/wirings/scope/scope.test.ts +1 -2
  769. package/src/wirings/scope/scope.types.ts +7 -9
  770. package/src/wirings/scope/validate-scope-definitions.ts +3 -21
  771. package/src/wirings/secret/index.ts +1 -1
  772. package/src/wirings/secret/secret.types.ts +19 -15
  773. package/src/wirings/secret/validate-secret-definitions.ts +2 -4
  774. package/src/wirings/trigger/trigger-runner.ts +1 -27
  775. package/src/wirings/trigger/trigger.types.ts +1 -82
  776. package/src/wirings/variable/index.ts +1 -1
  777. package/src/wirings/variable/validate-variable-definitions.ts +2 -4
  778. package/src/wirings/variable/variable.types.ts +1 -13
  779. package/src/wirings/virtual-user/index.ts +88 -0
  780. package/src/wirings/virtual-user/prepare-virtual-user-run.test.ts +115 -0
  781. package/src/wirings/virtual-user/prepare-virtual-user-run.ts +95 -0
  782. package/src/wirings/virtual-user/run-virtual-user.test.ts +765 -0
  783. package/src/wirings/virtual-user/run-virtual-user.ts +671 -0
  784. package/src/wirings/virtual-user/virtual-user-agents.test.ts +65 -0
  785. package/src/wirings/virtual-user/virtual-user-agents.ts +57 -0
  786. package/src/wirings/virtual-user/virtual-user-catalogue.test.ts +215 -0
  787. package/src/wirings/virtual-user/virtual-user-catalogue.ts +184 -0
  788. package/src/wirings/virtual-user/virtual-user-derive.test.ts +398 -0
  789. package/src/wirings/virtual-user/virtual-user-derive.ts +173 -0
  790. package/src/wirings/virtual-user/virtual-user-dispositions.test.ts +63 -0
  791. package/src/wirings/virtual-user/virtual-user-dispositions.ts +213 -0
  792. package/src/wirings/virtual-user/virtual-user-intents.test.ts +208 -0
  793. package/src/wirings/virtual-user/virtual-user-intents.ts +185 -0
  794. package/src/wirings/virtual-user/virtual-user-rng.test.ts +72 -0
  795. package/src/wirings/virtual-user/virtual-user-rng.ts +50 -0
  796. package/src/wirings/virtual-user/virtual-user-run-store.ts +98 -0
  797. package/src/wirings/virtual-user/virtual-user-target.ts +47 -0
  798. package/src/wirings/virtual-user/virtual-user.types.ts +219 -0
  799. package/src/wirings/workflow/dsl/workflow-dsl.types.ts +19 -20
  800. package/src/wirings/workflow/dsl/workflow-runner.ts +0 -4
  801. package/src/wirings/workflow/feature.ts +0 -19
  802. package/src/wirings/workflow/graph/graph-node.ts +0 -136
  803. package/src/wirings/workflow/graph/graph-runner.test.ts +20 -19
  804. package/src/wirings/workflow/graph/graph-runner.ts +6 -41
  805. package/src/wirings/workflow/graph/wire-workflow-graph.ts +0 -4
  806. package/src/wirings/workflow/graph/workflow-graph.types.ts +0 -58
  807. package/src/wirings/workflow/index.ts +10 -44
  808. package/src/wirings/workflow/pikku-scenario-service.ts +235 -61
  809. package/src/wirings/workflow/pikku-workflow-service.test.ts +0 -39
  810. package/src/wirings/workflow/pikku-workflow-service.ts +77 -674
  811. package/src/wirings/workflow/run-timeline.test.ts +7 -19
  812. package/src/wirings/workflow/run-timeline.ts +0 -56
  813. package/src/wirings/workflow/scenario-cookie-jar.test.ts +0 -1
  814. package/src/wirings/workflow/scenario-cookie-jar.ts +0 -25
  815. package/src/wirings/workflow/scenario-expectations.test.ts +2 -7
  816. package/src/wirings/workflow/scenario-hooks.test.ts +2 -7
  817. package/src/wirings/workflow/scenario-poll.test.ts +0 -2
  818. package/src/wirings/workflow/scenario-poll.ts +0 -15
  819. package/src/wirings/workflow/scenario-prose.test.ts +5 -7
  820. package/src/wirings/workflow/scenario-prose.ts +1 -29
  821. package/src/wirings/workflow/scenario-service.test.ts +2 -10
  822. package/src/wirings/workflow/scenario-step-guards.ts +1 -14
  823. package/src/wirings/workflow/scenario-step.test.ts +163 -19
  824. package/src/wirings/workflow/scenario-step.types.ts +94 -12
  825. package/src/wirings/workflow/scenario-surface.test.ts +146 -0
  826. package/src/wirings/workflow/scenario-surface.ts +71 -0
  827. package/src/wirings/workflow/workflow-dispatch-durability.test.ts +14 -15
  828. package/src/wirings/workflow/workflow-dispatch-payload.test.ts +0 -4
  829. package/src/wirings/workflow/workflow-inline-authority.test.ts +169 -0
  830. package/src/wirings/workflow/workflow-invocation-id.test.ts +0 -2
  831. package/src/wirings/workflow/workflow-invocation-id.ts +2 -22
  832. package/src/wirings/workflow/workflow-mirror.test.ts +0 -7
  833. package/src/wirings/workflow/workflow-on-error.test.ts +0 -9
  834. package/src/wirings/workflow/workflow-queue-workers.ts +0 -21
  835. package/src/wirings/workflow/workflow-replay-snapshot.test.ts +8 -7
  836. package/src/wirings/workflow/workflow-retry-policy.test.ts +0 -5
  837. package/src/wirings/workflow/workflow-run-context.test.ts +5 -10
  838. package/src/wirings/workflow/workflow-run-polling.test.ts +0 -5
  839. package/src/wirings/workflow/workflow-step-ordinal.test.ts +19 -4
  840. package/src/wirings/workflow/workflow-step-session.test.ts +0 -7
  841. package/src/wirings/workflow/workflow.types.ts +5 -201
  842. package/tsconfig.tsbuildinfo +1 -1
  843. package/tsconfig.type-tests.json +12 -0
  844. package/src/middleware/timeout.ts +0 -22
  845. package/src/pikku-response.ts +0 -5
  846. package/src/wirings/mcp/mcp-endpoint-registry.test.d.ts +0 -1
  847. package/src/wirings/workflow/dsl/index.ts +0 -36
  848. package/src/wirings/workflow/graph/index.ts +0 -15
@@ -0,0 +1,49 @@
1
+ import { flattenSystemRoleDefinitions } from '../role/validate-role-definitions.js';
2
+ import { deriveCatalogue, deriveIntents, } from './virtual-user-derive.js';
3
+ import { reachableAgents, } from './virtual-user-agents.js';
4
+ /**
5
+ * The scopes a persona holds, resolved through its roles.
6
+ *
7
+ * Roles are the only thing a persona declares; scopes are what a function
8
+ * checks. Narrowing a virtual user's catalogue needs the second, so the
9
+ * expansion happens once, here, against the same `defineSystemRole` definitions
10
+ * the seed grants from.
11
+ */
12
+ export const personaScopes = (persona, roleScopes) => {
13
+ const scopes = new Set();
14
+ for (const role of persona.roles ?? []) {
15
+ for (const scope of roleScopes[role] ?? []) {
16
+ scopes.add(scope);
17
+ }
18
+ }
19
+ return [...scopes].sort();
20
+ };
21
+ /**
22
+ * Derive what a virtual user needs from what the project already generates.
23
+ *
24
+ * Shared because there are two callers with the same problem and different
25
+ * sources for it: `pikku persona run` reads the inspector state at build time,
26
+ * and the scaffolded `runVirtualUser` RPC reads `metaService` at runtime. They
27
+ * must agree — a persona whose catalogue is narrower over RPC than on the CLI
28
+ * finds different things from the same seed, which is exactly the property a
29
+ * seed exists to give.
30
+ *
31
+ * Nothing here is authored for the virtual user's benefit: the function meta is
32
+ * the catalogue, the scenario meta is the intents, and the role definitions are
33
+ * what turn a persona's declared roles into the scopes a function checks.
34
+ */
35
+ export const prepareVirtualUserRun = (input) => {
36
+ const catalogue = deriveCatalogue(input.functionsMeta, input.schemas ?? {});
37
+ const intents = deriveIntents(input.workflowsMeta ?? {}, input.functionsMeta);
38
+ const declared = input.systemRoles ?? [];
39
+ const roleScopes = {};
40
+ for (const role of flattenSystemRoleDefinitions(Array.isArray(declared) ? declared : Object.values(declared))) {
41
+ roleScopes[role.name] = role.scopes;
42
+ }
43
+ const scopes = personaScopes(input.persona, roleScopes);
44
+ // Gated by the same scopes as the RPCs, because an agent is reached rather
45
+ // than declared: `CoreAIAgent.scopes` is checked against the session, so a
46
+ // persona finds the specialists its roles unlock and no others.
47
+ const agents = reachableAgents(input.agentsMeta ?? {}, scopes);
48
+ return { catalogue, intents, scopes, agents };
49
+ };
@@ -0,0 +1,92 @@
1
+ import type { ResolvedPersona } from '../../services/personas-service.js';
2
+ import type { ActorLLM } from '../actor-flow/run-conversation.js';
3
+ import { type VirtualUserTuning } from './virtual-user-dispositions.js';
4
+ import type { ApiCatalogueEntry, IntentSource, VirtualUserBudget, VirtualUserDisposition, VirtualUserFinding, VirtualUserRunResult, VirtualUserTally, VirtualUserTarget } from './virtual-user.types.js';
5
+ /** What an app-specific oracle is shown about one call. */
6
+ export interface VirtualUserCallContext {
7
+ rpcName: string;
8
+ args: unknown;
9
+ status: number;
10
+ ok: boolean;
11
+ body: unknown;
12
+ intentId?: string;
13
+ step: number;
14
+ disposition: VirtualUserDisposition;
15
+ }
16
+ export interface RunVirtualUserParams {
17
+ /** The person being run — name, job title, personality, goals. */
18
+ persona: ResolvedPersona;
19
+ /** The id they were declared under, as the intent sources refer to them. */
20
+ personaId: string;
21
+ /** How it behaves. Default `realistic`. */
22
+ disposition?: VirtualUserDisposition;
23
+ /** Per-user overrides for that disposition's dials. */
24
+ tuning?: VirtualUserTuning;
25
+ /** Every RPC the app exposes. Narrowed internally; nothing is hidden by default. */
26
+ catalogue: readonly ApiCatalogueEntry[];
27
+ /** Features and scenarios in the app's own words — never their step graphs. */
28
+ intents: readonly IntentSource[];
29
+ /** Extra goals in the user's own words, run alongside the derived intents. */
30
+ goals?: readonly string[];
31
+ /** The transport it acts through. */
32
+ target: VirtualUserTarget;
33
+ /** The user's own LLM. */
34
+ llm: ActorLLM;
35
+ model: string;
36
+ budget?: VirtualUserBudget;
37
+ /**
38
+ * The app's own stopping rule, given the running tally. Pikku counts steps,
39
+ * calls, mutations and tokens because only the engine sees them; what they
40
+ * cost is the app's to decide, which is why no price appears in core.
41
+ */
42
+ stop?: (tally: VirtualUserTally) => boolean | Promise<boolean>;
43
+ /** Fixed seed, so a run replays into the same finding. */
44
+ seed?: number;
45
+ /**
46
+ * Check a response against the RPC's own output schema. Supplied by the CLI
47
+ * from generated schemas; a mismatch means the contract and the implementation
48
+ * disagree, which nothing else in a normal test suite looks for.
49
+ */
50
+ validateOutput?: (rpcName: string, body: unknown) => string | null;
51
+ /** App-specific oracle — ownership, invariants, anything core cannot know. */
52
+ classify?: (context: VirtualUserCallContext) => VirtualUserFinding[] | null | undefined;
53
+ /** Files this user may upload. */
54
+ fixtures?: readonly string[];
55
+ /** Agents it may talk to. */
56
+ agents?: readonly {
57
+ name: string;
58
+ description?: string;
59
+ }[];
60
+ /** Ids and slugs remembered from an earlier run, for a `stale` user. */
61
+ memory?: Record<string, string>;
62
+ /**
63
+ * The scopes this persona actually holds, resolved from its roles at sign-in.
64
+ *
65
+ * Used two ways: to narrow a large catalogue to what it is entitled to reach,
66
+ * and as an oracle — a call whose scopes it does not hold that nonetheless
67
+ * succeeds is authorization drift.
68
+ */
69
+ scopes?: readonly string[];
70
+ /**
71
+ * Offer the endpoints the app marked as needing a human's approval. Off by
72
+ * default: those are the ones that spend money and move real traffic.
73
+ */
74
+ allowApprovalRequired?: boolean;
75
+ maxStepsPerIntent?: number;
76
+ }
77
+ /**
78
+ * Pull identifiers out of a response so later intents can refer to them.
79
+ *
80
+ * This is what makes a run cohesive without ever handing the user a dataflow
81
+ * map: it discovers that a project has an id by looking at one, the same way a
82
+ * person reads it off the screen.
83
+ */
84
+ export declare const rememberIds: (body: unknown, into: Record<string, string>, depth?: number) => Record<string, string>;
85
+ /**
86
+ * Run one virtual user against a live target until its budget runs out.
87
+ *
88
+ * The engine schedules which intent is live and the model decides what to do
89
+ * within it — that split is what lets a run be replayed from its seed while the
90
+ * work inside it stays genuinely open-ended.
91
+ */
92
+ export declare const runVirtualUser: (params: RunVirtualUserParams) => Promise<VirtualUserRunResult>;
@@ -0,0 +1,478 @@
1
+ import { getDurationInMilliseconds } from '../../time-utils.js';
2
+ import { catalogueIndex, catalogueLookup, describeEntry, isReadOnly, reachableCatalogue, renderCatalogue, } from './virtual-user-catalogue.js';
3
+ import { dispositionProfile, } from './virtual-user-dispositions.js';
4
+ import { IntentStack, intentsForPersona } from './virtual-user-intents.js';
5
+ import { createRng } from './virtual-user-rng.js';
6
+ /** One turn: what the user decided to do next, and why. */
7
+ const ACTION_SCHEMA = {
8
+ type: 'object',
9
+ properties: {
10
+ thought: { type: 'string' },
11
+ kind: {
12
+ type: 'string',
13
+ enum: ['describe', 'call', 'talkTo', 'upload', 'complete', 'stuck'],
14
+ },
15
+ rpcName: { type: 'string' },
16
+ /**
17
+ * A JSON object, as a string. Not `type: 'object'`: structured output is
18
+ * strict, and a schema-less object is the one thing strict mode cannot
19
+ * express — OpenAI rejects the whole request with "'additionalProperties'
20
+ * is required to be supplied and to be false", so every turn 400s and the
21
+ * run never takes a step. The arguments differ per endpoint and are only
22
+ * known from the `describe` the user just did, so there is no schema to
23
+ * give here; a string is how a free-form object crosses that boundary.
24
+ */
25
+ args: { type: 'string' },
26
+ agent: { type: 'string' },
27
+ task: { type: 'string' },
28
+ file: { type: 'string' },
29
+ summary: { type: 'string' },
30
+ },
31
+ required: ['kind'],
32
+ };
33
+ const DEFAULT_MAX_STEPS = 40;
34
+ const DEFAULT_MAX_STEPS_PER_INTENT = 20;
35
+ const RESPONSE_EXCERPT = 600;
36
+ const msg = (role, content) => ({
37
+ id: globalThis.crypto.randomUUID(),
38
+ role,
39
+ content,
40
+ createdAt: new Date(),
41
+ });
42
+ /** Read a structured result, falling back to parsing JSON out of the text. */
43
+ const readObject = (result) => {
44
+ if (result.object && typeof result.object === 'object')
45
+ return result.object;
46
+ if (result.text) {
47
+ try {
48
+ return JSON.parse(result.text);
49
+ }
50
+ catch {
51
+ return null;
52
+ }
53
+ }
54
+ return null;
55
+ };
56
+ /**
57
+ * The arguments for a call, however the model chose to spell them.
58
+ *
59
+ * `ACTION_SCHEMA` asks for a JSON string because strict structured output
60
+ * cannot carry a schema-less object, but a model reading the endpoint's own
61
+ * schema will sometimes send the object anyway, and a scripted or non-strict
62
+ * provider always will. Both are the same intent, so both are accepted; text
63
+ * that is not JSON at all is not arguments, and calling with it would only
64
+ * produce a 400 attributable to the wrong thing.
65
+ */
66
+ const readArgs = (args) => {
67
+ if (args && typeof args === 'object')
68
+ return args;
69
+ if (typeof args === 'string' && args.trim()) {
70
+ try {
71
+ const parsed = JSON.parse(args);
72
+ if (parsed && typeof parsed === 'object') {
73
+ return parsed;
74
+ }
75
+ }
76
+ catch {
77
+ // Not JSON — fall through to no arguments.
78
+ }
79
+ }
80
+ return {};
81
+ };
82
+ /** Keys worth remembering across intents — the things a person writes down. */
83
+ const MEMORABLE = /(id|slug|token|email|name|key|url|code)$/i;
84
+ /**
85
+ * Pull identifiers out of a response so later intents can refer to them.
86
+ *
87
+ * This is what makes a run cohesive without ever handing the user a dataflow
88
+ * map: it discovers that a project has an id by looking at one, the same way a
89
+ * person reads it off the screen.
90
+ */
91
+ export const rememberIds = (body, into, depth = 0) => {
92
+ if (depth > 4 || body === null || typeof body !== 'object')
93
+ return into;
94
+ if (Array.isArray(body)) {
95
+ for (const item of body.slice(0, 5))
96
+ rememberIds(item, into, depth + 1);
97
+ return into;
98
+ }
99
+ for (const [key, value] of Object.entries(body)) {
100
+ if (typeof value === 'string' && MEMORABLE.test(key) && value.length < 200) {
101
+ into[key] = value;
102
+ }
103
+ else if (typeof value === 'object') {
104
+ rememberIds(value, into, depth + 1);
105
+ }
106
+ }
107
+ return into;
108
+ };
109
+ const personaInstructions = (persona, profile, catalogue, agents, fixtures) => [
110
+ `You are a real person using a product through its API. Stay in character; you are the user, not the system.`,
111
+ `Your name is ${persona.name}.`,
112
+ persona.jobTitle ? `Your role: ${persona.jobTitle}.` : '',
113
+ persona.personality ? `Your manner: ${persona.personality}.` : '',
114
+ '',
115
+ profile.instructions,
116
+ '',
117
+ `Each turn you take exactly ONE action:`,
118
+ `- describe: read an endpoint's schema. You MUST describe an endpoint before you may call it.`,
119
+ `- call: invoke an endpoint with arguments that fit its schema. Put them in 'args' as a JSON object written as a string, e.g. "{\\"id\\":\\"abc\\"}".`,
120
+ agents.length
121
+ ? `- talkTo: ask one of the product's assistants to do something for you in plain language.`
122
+ : '',
123
+ fixtures.length ? `- upload: send one of your files.` : '',
124
+ `- complete: you got what you came for.`,
125
+ `- stuck: you cannot get there, and you can say why.`,
126
+ '',
127
+ agents.length
128
+ ? `Assistants you can talk to:\n${agents
129
+ .map((agent) => `- ${agent.name}${agent.description ? `: ${agent.description}` : ''}`)
130
+ .join('\n')}`
131
+ : '',
132
+ fixtures.length ? `Files you have: ${fixtures.join(', ')}` : '',
133
+ '',
134
+ `The endpoints available to you, as name(inputs) -> outputs:`,
135
+ catalogue,
136
+ ]
137
+ .filter(Boolean)
138
+ .join('\n');
139
+ /**
140
+ * Run one virtual user against a live target until its budget runs out.
141
+ *
142
+ * The engine schedules which intent is live and the model decides what to do
143
+ * within it — that split is what lets a run be replayed from its seed while the
144
+ * work inside it stays genuinely open-ended.
145
+ */
146
+ export const runVirtualUser = async (params) => {
147
+ const { persona, personaId, disposition = 'realistic', tuning, target, llm, model, budget, stop, validateOutput, classify, fixtures = [], agents = [], scopes, allowApprovalRequired = false, maxStepsPerIntent = DEFAULT_MAX_STEPS_PER_INTENT, } = params;
148
+ const profile = dispositionProfile(disposition, tuning);
149
+ const seed = params.seed ?? Math.floor(Math.random() * 2 ** 31);
150
+ const rng = createRng(seed);
151
+ const startedAt = Date.now();
152
+ // An adversarial user is offered the whole surface on purpose — probing what
153
+ // it should not reach is the behaviour under test — while `scopes` stays live
154
+ // below as the oracle that says a success there was a finding.
155
+ const reachable = reachableCatalogue(params.catalogue, {
156
+ readOnly: profile.readOnly,
157
+ allowApprovalRequired,
158
+ scopes: profile.invertedOracle ? undefined : scopes,
159
+ });
160
+ const index = catalogueIndex(reachable);
161
+ const sources = [
162
+ ...intentsForPersona(params.intents, personaId),
163
+ ...(params.goals ?? []).map((goal, i) => ({
164
+ id: `goal_${i + 1}`,
165
+ title: goal,
166
+ })),
167
+ ];
168
+ const stack = new IntentStack(sources, rng, profile);
169
+ const memory = profile.emptyMemory
170
+ ? {}
171
+ : { ...(params.memory ?? {}) };
172
+ const described = new Set();
173
+ const findings = [];
174
+ const steps = [];
175
+ const history = new Map();
176
+ const tally = {
177
+ steps: 0,
178
+ calls: 0,
179
+ mutations: 0,
180
+ tokensIn: 0,
181
+ tokensOut: 0,
182
+ model,
183
+ elapsedMs: 0,
184
+ findings: 0,
185
+ };
186
+ const maxSteps = budget?.steps ?? DEFAULT_MAX_STEPS;
187
+ const maxDurationMs = budget?.duration === undefined
188
+ ? undefined
189
+ : typeof budget.duration === 'number'
190
+ ? budget.duration
191
+ : getDurationInMilliseconds(budget.duration);
192
+ const instructions = personaInstructions(persona, profile, renderCatalogue(reachable), agents, fixtures);
193
+ const addFinding = (finding) => {
194
+ findings.push(finding);
195
+ tally.findings++;
196
+ };
197
+ // Every other exit sets this and breaks; running the loop out means the step
198
+ // budget is what ended it.
199
+ let stoppedBy = 'budget-steps';
200
+ for (let step = 0; step < maxSteps; step++) {
201
+ tally.elapsedMs = Date.now() - startedAt;
202
+ if (maxDurationMs !== undefined && tally.elapsedMs >= maxDurationMs) {
203
+ stoppedBy = 'budget-duration';
204
+ break;
205
+ }
206
+ if (budget?.mutations !== undefined && tally.mutations >= budget.mutations) {
207
+ stoppedBy = 'budget-mutations';
208
+ break;
209
+ }
210
+ if (stop && (await stop({ ...tally }))) {
211
+ stoppedBy = 'stop-hook';
212
+ break;
213
+ }
214
+ const tick = stack.next(step);
215
+ if (!tick) {
216
+ // Nothing left to schedule: either this user was given no intents at all,
217
+ // or it saw every one of them through.
218
+ stoppedBy = stack.records().length === 0 ? 'no-intents' : 'exhausted';
219
+ break;
220
+ }
221
+ // A user who cannot get anywhere gives up rather than looping forever.
222
+ if (tick.intent.steps.length > maxStepsPerIntent) {
223
+ stack.stuck('gave up after going in circles');
224
+ continue;
225
+ }
226
+ const intentId = tick.intent.id;
227
+ if (!history.has(intentId)) {
228
+ const source = tick.intent.source;
229
+ history.set(intentId, [
230
+ msg('user', [
231
+ `What you want to do right now: ${source.title}`,
232
+ source.description ?? '',
233
+ source.steps?.length
234
+ ? `Roughly how it goes:\n${source.steps.map((s) => `- ${s}`).join('\n')}`
235
+ : '',
236
+ `Work it out through the API yourself — nobody has told you which endpoints do this.`,
237
+ ]
238
+ .filter(Boolean)
239
+ .join('\n')),
240
+ ]);
241
+ }
242
+ const messages = history.get(intentId);
243
+ if (tick.move === 'resume' || tick.move === 'suspend') {
244
+ messages.push(msg('user', `You were pulled away and have come back to this. Things may have changed since.`));
245
+ }
246
+ // Whether this user trusts its notes this turn or goes and looks again.
247
+ // `stale` almost always trusts them, a newcomer has none to trust, and an
248
+ // auditor checks nearly everything — which is the whole difference between
249
+ // those runs, expressed as one roll rather than as prose.
250
+ if (Object.keys(memory).length && !rng.chance(profile.reReadRate)) {
251
+ messages.push(msg('user', `Things you have noted down: ${Object.entries(memory)
252
+ .slice(-25)
253
+ .map(([key, value]) => `${key}=${value}`)
254
+ .join(', ')}`));
255
+ }
256
+ else if (Object.keys(memory).length) {
257
+ messages.push(msg('user', `You are not sure your notes are current. Look things up.`));
258
+ }
259
+ const result = await llm({
260
+ model,
261
+ temperature: profile.temperature,
262
+ instructions,
263
+ messages,
264
+ tools: [],
265
+ maxSteps: 1,
266
+ toolChoice: 'none',
267
+ outputSchema: ACTION_SCHEMA,
268
+ });
269
+ tally.steps++;
270
+ tally.tokensIn += result.usage?.inputTokens ?? 0;
271
+ tally.tokensOut += result.usage?.outputTokens ?? 0;
272
+ const raw = readObject(result);
273
+ const record = {
274
+ index: step,
275
+ intentId,
276
+ action: { kind: 'invalid', detail: 'no action produced' },
277
+ tokensIn: result.usage?.inputTokens ?? 0,
278
+ tokensOut: result.usage?.outputTokens ?? 0,
279
+ };
280
+ if (!raw || typeof raw.kind !== 'string') {
281
+ steps.push(record);
282
+ messages.push(msg('user', 'That was not a valid action. Choose one action.'));
283
+ continue;
284
+ }
285
+ const action = { ...raw, kind: raw.kind };
286
+ record.action = action;
287
+ messages.push(msg('assistant', JSON.stringify(raw)));
288
+ /** Tell the user what happened, so the next turn is informed. */
289
+ const reply = (text) => messages.push(msg('user', text));
290
+ if (action.kind === 'complete') {
291
+ stack.complete(action.summary);
292
+ steps.push(record);
293
+ continue;
294
+ }
295
+ if (action.kind === 'stuck') {
296
+ stack.stuck(action.reason);
297
+ steps.push(record);
298
+ continue;
299
+ }
300
+ if (action.kind === 'describe') {
301
+ const entry = catalogueLookup(index, action.rpcName);
302
+ if (!entry) {
303
+ reply(`There is no endpoint called '${action.rpcName}'.`);
304
+ steps.push(record);
305
+ continue;
306
+ }
307
+ described.add(entry.name);
308
+ // Saying the gate is now open matters: reading a schema is free and
309
+ // calling is not, so a model left to infer it will happily spend a whole
310
+ // budget describing one endpoint after another and never touch the app.
311
+ reply(`${JSON.stringify(describeEntry(entry))}\nYou have read this one, so you may now call '${entry.name}'.`);
312
+ steps.push(record);
313
+ continue;
314
+ }
315
+ if (action.kind === 'talkTo') {
316
+ if (!target.talkTo) {
317
+ reply('There is nobody to talk to here.');
318
+ steps.push(record);
319
+ continue;
320
+ }
321
+ const verdict = await target.talkTo(action.agent, action.task);
322
+ record.ok = verdict.passed;
323
+ record.response = verdict.reasoning.slice(0, RESPONSE_EXCERPT);
324
+ reply(`You spoke to ${action.agent}. ${verdict.passed ? 'It sorted it out.' : 'It did not.'} ${verdict.reasoning}`);
325
+ steps.push(record);
326
+ continue;
327
+ }
328
+ if (action.kind === 'upload') {
329
+ if (!target.upload) {
330
+ reply('You have nowhere to send a file.');
331
+ steps.push(record);
332
+ continue;
333
+ }
334
+ const response = await target.upload(action.file);
335
+ record.status = response.status;
336
+ record.ok = response.ok;
337
+ record.response = response.serialized.slice(0, RESPONSE_EXCERPT);
338
+ if (response.status >= 500) {
339
+ record.findingKinds = ['server-error'];
340
+ addFinding({
341
+ kind: 'server-error',
342
+ detail: `upload '${action.file}' returned ${response.status}`,
343
+ status: response.status,
344
+ intentId,
345
+ step,
346
+ });
347
+ }
348
+ reply(`Upload came back ${response.status}: ${record.response}`);
349
+ steps.push(record);
350
+ continue;
351
+ }
352
+ // Everything below is a call.
353
+ const entry = catalogueLookup(index, action.rpcName);
354
+ if (!entry) {
355
+ reply(`There is no endpoint called '${action.rpcName}'.`);
356
+ steps.push(record);
357
+ continue;
358
+ }
359
+ if (!described.has(entry.name)) {
360
+ // Enforced rather than merely asked for: guessing field names is
361
+ // unproductive fuzz that turns every 400 into a typo. Handing back the
362
+ // schema makes this self-correcting in one turn.
363
+ reply(`You do not know this endpoint's fields yet. Its schema is: ${JSON.stringify(describeEntry(entry))}`);
364
+ described.add(entry.name);
365
+ steps.push(record);
366
+ continue;
367
+ }
368
+ // What may be called is decided once, when the catalogue is narrowed: a
369
+ // read-only disposition is never offered a mutation and an approval-gated
370
+ // endpoint is never offered at all, so `index` is the gate and there is no
371
+ // second one here to drift out of step with it.
372
+ const mutating = !isReadOnly(entry);
373
+ const args = readArgs(action.args);
374
+ const repeats = profile.repeatRate > 0 && rng.chance(profile.repeatRate) ? 2 : 1;
375
+ let lastResponseText = '';
376
+ for (let attempt = 0; attempt < repeats; attempt++) {
377
+ let response;
378
+ try {
379
+ response = await target.call(entry.name, args);
380
+ }
381
+ catch (error) {
382
+ record.findingKinds = [...(record.findingKinds ?? []), 'transport-error'];
383
+ addFinding({
384
+ kind: 'transport-error',
385
+ detail: `${entry.name} threw: ${error.message}`,
386
+ rpcName: entry.name,
387
+ intentId,
388
+ step,
389
+ });
390
+ lastResponseText = `The request failed outright: ${error.message}`;
391
+ break;
392
+ }
393
+ tally.calls++;
394
+ if (mutating)
395
+ tally.mutations++;
396
+ record.status = response.status;
397
+ record.ok = response.ok;
398
+ record.response = response.serialized.slice(0, RESPONSE_EXCERPT);
399
+ lastResponseText = `${response.status}: ${record.response}`;
400
+ const kinds = [];
401
+ if (response.status >= 500) {
402
+ kinds.push('server-error');
403
+ addFinding({
404
+ kind: 'server-error',
405
+ detail: `${entry.name} returned ${response.status}`,
406
+ rpcName: entry.name,
407
+ status: response.status,
408
+ intentId,
409
+ step,
410
+ });
411
+ }
412
+ if (response.ok && validateOutput) {
413
+ const problem = validateOutput(entry.name, response.body);
414
+ if (problem) {
415
+ kinds.push('schema-violation');
416
+ addFinding({
417
+ kind: 'schema-violation',
418
+ detail: `${entry.name} answered outside its own output schema: ${problem}`,
419
+ rpcName: entry.name,
420
+ status: response.status,
421
+ intentId,
422
+ step,
423
+ });
424
+ }
425
+ }
426
+ // This persona does not hold the scopes this endpoint declares, and the
427
+ // server served it anyway — the declaration and the enforcement disagree.
428
+ if (response.ok &&
429
+ scopes &&
430
+ entry.scopes?.some((scope) => !scopes.includes(scope))) {
431
+ kinds.push('unexpected-success');
432
+ addFinding({
433
+ kind: 'unexpected-success',
434
+ detail: `${entry.name} succeeded for '${personaId}', who does not hold ${entry.scopes
435
+ .filter((scope) => !scopes.includes(scope))
436
+ .join(', ')}`,
437
+ rpcName: entry.name,
438
+ status: response.status,
439
+ intentId,
440
+ step,
441
+ });
442
+ }
443
+ for (const finding of classify?.({
444
+ rpcName: entry.name,
445
+ args,
446
+ status: response.status,
447
+ ok: response.ok,
448
+ body: response.body,
449
+ intentId,
450
+ step,
451
+ disposition,
452
+ }) ?? []) {
453
+ kinds.push(finding.kind);
454
+ addFinding({ ...finding, step });
455
+ }
456
+ if (kinds.length) {
457
+ record.findingKinds = [...(record.findingKinds ?? []), ...kinds];
458
+ }
459
+ if (response.ok)
460
+ rememberIds(response.body, memory);
461
+ if (attempt + 1 < repeats) {
462
+ lastResponseText += ` (you were not sure it went through, so you sent it again)`;
463
+ }
464
+ }
465
+ reply(lastResponseText);
466
+ steps.push(record);
467
+ }
468
+ tally.elapsedMs = Date.now() - startedAt;
469
+ return {
470
+ seed,
471
+ tally,
472
+ findings,
473
+ intents: stack.records(),
474
+ steps,
475
+ memory,
476
+ stoppedBy,
477
+ };
478
+ };
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Which of the product's agents a persona can actually talk to.
3
+ *
4
+ * An agent is not something a persona declares. It is something a persona
5
+ * *reaches*, under exactly the rule an RPC is reached by: `CoreAIAgent.scopes`
6
+ * is checked against the session, so a persona holding the scopes an agent
7
+ * requires finds it in front of them, and one that does not, does not.
8
+ *
9
+ * That is the whole reason a persona has no `agent:` field. Naming one would
10
+ * add no capability the roles do not already confer, and would narrow the
11
+ * persona to a single brain when the interesting behaviour is the choice
12
+ * between calling the API directly and handing the work to a specialist.
13
+ */
14
+ /** The part of an agent's meta this needs. */
15
+ export interface AgentReachability {
16
+ name?: string;
17
+ description?: string;
18
+ scopes?: readonly string[];
19
+ auth?: boolean;
20
+ }
21
+ /** One agent, as it is offered to a virtual user. */
22
+ export interface ReachableAgent {
23
+ name: string;
24
+ description?: string;
25
+ }
26
+ /**
27
+ * The agents to offer, keyed by the name they are declared under.
28
+ *
29
+ * Like {@link reachableCatalogue}, this narrows *what is offered* and never
30
+ * what is enforced: the server decides who may talk to what, and an agent
31
+ * answering a persona this filter would have withheld is a finding rather than
32
+ * a bug here.
33
+ *
34
+ * An agent declaring no scopes is offered to everybody, on the same terms as a
35
+ * function that gates itself with none — undeclared is not the same as denied,
36
+ * and inventing a denial here would hide the endpoints that really are open.
37
+ */
38
+ export declare const reachableAgents: (agents: Readonly<Record<string, AgentReachability>>, scopes?: readonly string[]) => ReachableAgent[];
@@ -0,0 +1,24 @@
1
+ import { hasScopes } from '../../scopes.js';
2
+ /**
3
+ * The agents to offer, keyed by the name they are declared under.
4
+ *
5
+ * Like {@link reachableCatalogue}, this narrows *what is offered* and never
6
+ * what is enforced: the server decides who may talk to what, and an agent
7
+ * answering a persona this filter would have withheld is a finding rather than
8
+ * a bug here.
9
+ *
10
+ * An agent declaring no scopes is offered to everybody, on the same terms as a
11
+ * function that gates itself with none — undeclared is not the same as denied,
12
+ * and inventing a denial here would hide the endpoints that really are open.
13
+ */
14
+ export const reachableAgents = (agents, scopes) => Object.entries(agents)
15
+ .filter(([, agent]) => {
16
+ if (!scopes || !agent.scopes?.length) {
17
+ return true;
18
+ }
19
+ return hasScopes(agent.scopes, scopes);
20
+ })
21
+ .map(([id, agent]) => ({
22
+ name: agent.name ?? id,
23
+ ...(agent.description ? { description: agent.description } : {}),
24
+ }));