@pikku/core 0.12.139 → 0.12.142

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 (253) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/dist/errors/errors.d.ts +1 -1
  3. package/dist/errors/errors.js +1 -1
  4. package/dist/function/function-meta.types.d.ts +6 -6
  5. package/dist/function/functions.types.d.ts +2 -2
  6. package/dist/lifecycle.d.ts +6 -0
  7. package/dist/lifecycle.js +58 -0
  8. package/dist/services/audit-service.d.ts +4 -4
  9. package/dist/services/feature-flag-service.d.ts +3 -3
  10. package/dist/services/{http-personas.d.ts → http-virtual-users.d.ts} +25 -47
  11. package/dist/services/{http-personas.js → http-virtual-users.js} +29 -53
  12. package/dist/services/index.d.ts +2 -2
  13. package/dist/services/index.js +1 -1
  14. package/dist/services/meta-service.d.ts +6 -6
  15. package/dist/services/meta-service.js +8 -8
  16. package/dist/{wirings/workflow → services}/scenario-cookie-jar.d.ts +2 -0
  17. package/dist/{wirings/workflow → services}/scenario-cookie-jar.js +18 -14
  18. package/dist/services/scoped-secret-service.d.ts +1 -0
  19. package/dist/services/scoped-secret-service.js +3 -0
  20. package/dist/services/secret-service.d.ts +6 -0
  21. package/dist/services/system-role-guard.d.ts +1 -1
  22. package/dist/services/typed-secret-service.d.ts +1 -0
  23. package/dist/services/typed-secret-service.js +7 -0
  24. package/dist/services/virtual-user-sign-in.d.ts +52 -0
  25. package/dist/services/virtual-user-sign-in.js +80 -0
  26. package/dist/services/virtual-user-statement.d.ts +31 -0
  27. package/dist/services/virtual-user-statement.js +24 -0
  28. package/dist/services/{personas-service.d.ts → virtual-users-service.d.ts} +25 -23
  29. package/dist/services/{personas-service.js → virtual-users-service.js} +3 -3
  30. package/dist/testing/service-tests/secret-service-tests.js +9 -0
  31. package/dist/types/core.types.d.ts +11 -11
  32. package/dist/utils.d.ts +2 -5
  33. package/dist/utils.js +1 -38
  34. package/dist/wirings/cli/cli-runner.js +24 -9
  35. package/dist/wirings/http/http-runner.js +4 -0
  36. package/dist/wirings/http/http.types.d.ts +1 -0
  37. package/dist/wirings/http/pikku-fetch-http-response.d.ts +1 -0
  38. package/dist/wirings/http/pikku-fetch-http-response.js +12 -0
  39. package/dist/wirings/http/web-request.js +7 -0
  40. package/dist/wirings/role/define-system-role.d.ts +1 -1
  41. package/dist/wirings/role/define-system-role.js +1 -1
  42. package/dist/wirings/{actor-flow/actor-flow.types.d.ts → virtual-user/conversation/conversation.types.d.ts} +5 -5
  43. package/dist/wirings/virtual-user/conversation/index.d.ts +2 -0
  44. package/dist/wirings/virtual-user/conversation/run-conversation.d.ts +36 -0
  45. package/dist/wirings/{actor-flow → virtual-user/conversation}/run-conversation.js +30 -30
  46. package/dist/wirings/virtual-user/define-virtual-users.d.ts +32 -0
  47. package/dist/wirings/{persona/define-personas.js → virtual-user/define-virtual-users.js} +9 -9
  48. package/dist/wirings/virtual-user/index.d.ts +30 -7
  49. package/dist/wirings/virtual-user/index.js +23 -4
  50. package/dist/wirings/virtual-user/prepare-virtual-user-run.d.ts +8 -8
  51. package/dist/wirings/virtual-user/prepare-virtual-user-run.js +9 -9
  52. package/dist/wirings/virtual-user/run-virtual-user.d.ts +6 -6
  53. package/dist/wirings/virtual-user/run-virtual-user.js +10 -10
  54. package/dist/wirings/{persona/validate-personas.d.ts → virtual-user/validate-virtual-users.d.ts} +11 -11
  55. package/dist/wirings/{persona/validate-personas.js → virtual-user/validate-virtual-users.js} +24 -24
  56. package/dist/wirings/virtual-user/virtual-user-agents.d.ts +7 -7
  57. package/dist/wirings/virtual-user/virtual-user-agents.js +2 -2
  58. package/dist/wirings/{persona/persona-app-scopes.d.ts → virtual-user/virtual-user-app-scopes.d.ts} +10 -10
  59. package/dist/wirings/{persona/persona-app-scopes.js → virtual-user/virtual-user-app-scopes.js} +12 -12
  60. package/dist/wirings/virtual-user/virtual-user-catalogue.d.ts +3 -3
  61. package/dist/wirings/virtual-user/virtual-user-catalogue.js +2 -2
  62. package/dist/wirings/{persona/persona.types.d.ts → virtual-user/virtual-user-declaration.types.d.ts} +24 -24
  63. package/dist/wirings/virtual-user/virtual-user-derive.js +13 -7
  64. package/dist/wirings/virtual-user/virtual-user-dispositions.d.ts +1 -1
  65. package/dist/wirings/{persona/persona-email.d.ts → virtual-user/virtual-user-email.d.ts} +11 -11
  66. package/dist/wirings/{persona/persona-email.js → virtual-user/virtual-user-email.js} +19 -19
  67. package/dist/wirings/{persona/persona-environments.d.ts → virtual-user/virtual-user-environments.d.ts} +10 -10
  68. package/dist/wirings/{persona/persona-environments.js → virtual-user/virtual-user-environments.js} +21 -21
  69. package/dist/wirings/virtual-user/virtual-user-intents.d.ts +3 -3
  70. package/dist/wirings/virtual-user/virtual-user-intents.js +3 -3
  71. package/dist/wirings/{persona/persona-mailbox.d.ts → virtual-user/virtual-user-mailbox.d.ts} +4 -4
  72. package/dist/wirings/virtual-user/virtual-user-run-store.d.ts +4 -4
  73. package/dist/wirings/virtual-user/virtual-user-scaffold.d.ts +42 -61
  74. package/dist/wirings/virtual-user/virtual-user-scaffold.js +69 -117
  75. package/dist/wirings/virtual-user/virtual-user-schedule-store.d.ts +15 -15
  76. package/dist/wirings/virtual-user/virtual-user-schedule.d.ts +6 -6
  77. package/dist/wirings/virtual-user/virtual-user-schedule.js +11 -11
  78. package/dist/wirings/virtual-user/virtual-user-target.d.ts +6 -6
  79. package/dist/wirings/virtual-user/virtual-user-target.js +5 -5
  80. package/dist/wirings/virtual-user/virtual-user.types.d.ts +11 -11
  81. package/dist/wirings/virtual-user/virtual-user.types.js +1 -1
  82. package/dist/wirings/workflow/dsl/workflow-dsl.types.d.ts +9 -9
  83. package/dist/wirings/workflow/pikku-scenario-service.d.ts +28 -28
  84. package/dist/wirings/workflow/pikku-scenario-service.js +77 -77
  85. package/dist/wirings/workflow/pikku-workflow-service.d.ts +2 -2
  86. package/dist/wirings/workflow/pikku-workflow-service.js +4 -4
  87. package/dist/wirings/workflow/scenario-prose.d.ts +8 -8
  88. package/dist/wirings/workflow/scenario-prose.js +12 -8
  89. package/dist/wirings/workflow/scenario-run.types.d.ts +13 -13
  90. package/dist/wirings/workflow/scenario-step.types.d.ts +23 -23
  91. package/dist/wirings/workflow/workflow.types.d.ts +2 -2
  92. package/knowledge/decisions/index.md +0 -2
  93. package/knowledge/decisions/internals/a-credential-name-declared-twice-must-agree-on-schema-and-type.md +29 -0
  94. package/knowledge/decisions/internals/a-grant-can-name-a-scope-declared-without-its-addon.md +29 -0
  95. package/knowledge/decisions/internals/a-scheduled-task-writes-its-caller-session-before-it-runs.md +22 -0
  96. package/knowledge/decisions/internals/a-secret-set-in-memory-shadows-the-variable-of-the-same-name.md +28 -0
  97. package/knowledge/decisions/internals/a-virtual-user-acts-through-invokeraw-so-a-refusal-is-data.md +32 -0
  98. package/knowledge/decisions/internals/a-virtual-user-cadence-is-a-row-not-a-timer.md +12 -12
  99. package/knowledge/decisions/internals/a-virtual-user-converse-signs-in-before-its-first-turn.md +24 -0
  100. package/knowledge/decisions/internals/a-virtual-user-email-is-computed-with-the-run-id-as-a-sub-address.md +34 -0
  101. package/knowledge/decisions/internals/a-virtual-user-run-is-not-a-workflow-but-it-needs-a-trigger.md +2 -2
  102. package/knowledge/decisions/internals/an-agent-is-offered-under-its-registry-key-and-only-within-the-virtual-users-scopes.md +27 -0
  103. package/knowledge/decisions/internals/an-oauth2-credential-implies-an-optional-app-secret.md +26 -0
  104. package/knowledge/decisions/internals/analytics-identity-resolvers-run-in-declared-order.md +22 -0
  105. package/knowledge/decisions/internals/feature-flag-declarations-refuse-an-empty-anyof-and-conflicting-scopes.md +22 -0
  106. package/knowledge/decisions/internals/feature-flags-fail-open-and-never-enforce-access.md +28 -0
  107. package/knowledge/decisions/internals/flag-sync-rewrites-only-the-declared-text.md +24 -0
  108. package/knowledge/decisions/internals/in-a-scenario-a-4xx-is-data-not-an-exception.md +3 -3
  109. package/knowledge/decisions/internals/index.md +46 -31
  110. package/knowledge/decisions/internals/one-project-shape-check-two-validators.md +10 -10
  111. package/knowledge/decisions/internals/role-names-cannot-contain-the-scope-separator.md +30 -0
  112. package/knowledge/decisions/internals/scenario-agent-calls-sign-in-on-401-only.md +23 -19
  113. package/knowledge/decisions/internals/scenario-steps-return-drained-response-records.md +2 -2
  114. package/knowledge/decisions/internals/scenarios-live-in-files-named-for-them.md +12 -12
  115. package/knowledge/decisions/internals/the-core-scope-validator-refuses-separator-wildcard-and-empty-segments.md +22 -0
  116. package/knowledge/decisions/internals/the-pikku-user-id-resolves-in-a-fixed-order.md +24 -0
  117. package/knowledge/decisions/internals/{the-actor-prompt-says-json-because-of-json-object-mode.md → the-virtual-user-prompt-says-json-because-of-json-object-mode.md} +4 -4
  118. package/knowledge/decisions/internals/{the-persona-runtime-is-exported-from-the-persona-entry-point.md → the-virtual-user-runtime-is-exported-from-the-virtual-user-entry-point.md} +8 -8
  119. package/knowledge/decisions/internals/validate-checks-virtual-users-through-a-shared-module.md +43 -0
  120. package/knowledge/decisions/internals/{actor-flow-drives-the-target-through-a-transport-seam.md → virtual-user-conversation-drives-the-target-through-a-transport-seam.md} +6 -6
  121. package/knowledge/decisions/internals/virtual-user-conversation-verdicts-are-llm-self-evaluations.md +25 -0
  122. package/knowledge/decisions/internals/virtual-user-conversations-seed-a-hidden-kickoff-message.md +23 -0
  123. package/knowledge/decisions/internals/virtual-users-are-declared-in-one-definevirtualusers-call-per-codebase.md +30 -0
  124. package/knowledge/decisions/internals/workflow-core-never-imports-a-browser-driver.md +5 -5
  125. package/knowledge/decisions/internals/workflow-run-capabilities-are-extensions-not-subclasses.md +2 -2
  126. package/knowledge/decisions/internals/workflow-scenario-assertions-never-retry-and-record-one-step.md +4 -4
  127. package/knowledge/decisions/internals/workflow-scenario-hooks-are-a-scenario-only-affordance.md +1 -1
  128. package/knowledge/decisions/internals/workflow-scenario-prose-is-rendered-from-typed-calls-not-parsed-from-english.md +2 -2
  129. package/knowledge/decisions/internals/workflow-scenario-step-targets-are-string-literals-for-the-inspector.md +1 -1
  130. package/knowledge/decisions/internals/workflow-suspended-runs-keep-their-in-process-context.md +1 -1
  131. package/knowledge/decisions/security/a-bearer-token-checked-against-a-secret-reads-it-per-request.md +26 -0
  132. package/knowledge/decisions/security/a-call-without-a-session-raises-missing-session-not-forbidden.md +20 -0
  133. package/knowledge/decisions/security/a-caller-cookie-wins-over-the-jar-for-the-same-name.md +23 -0
  134. package/knowledge/decisions/security/a-channel-lifecycle-acts-as-the-socket-upgrade-session.md +16 -0
  135. package/knowledge/decisions/security/a-channel-requires-a-session-unless-it-says-auth-false.md +26 -0
  136. package/knowledge/decisions/security/a-credential-read-path-follows-its-declared-type-not-absence.md +32 -0
  137. package/knowledge/decisions/security/a-credential-type-is-a-literal-the-inspector-checks-at-declaration.md +27 -0
  138. package/knowledge/decisions/security/a-first-party-cookie-is-written-only-after-its-purposes-consent.md +33 -0
  139. package/knowledge/decisions/security/a-readonly-session-reaches-only-readonly-functions.md +25 -0
  140. package/knowledge/decisions/security/a-scaffold-flag-says-a-surface-exists-not-who-may-call-it.md +10 -5
  141. package/knowledge/decisions/security/a-scheduled-virtual-user-run-needs-no-admin-at-run-time.md +27 -0
  142. package/knowledge/decisions/security/a-scoped-credential-view-is-limited-to-declared-names.md +26 -0
  143. package/knowledge/decisions/security/a-scoped-secret-view-reads-only-declared-keys-and-never-writes.md +25 -0
  144. package/knowledge/decisions/security/a-secret-is-sent-only-to-the-hosts-it-declares.md +29 -0
  145. package/knowledge/decisions/security/a-step-can-name-an-identity-no-virtual-user-holds-through-per-call-headers.md +25 -0
  146. package/knowledge/decisions/security/a-stopped-run-by-id-skips-the-ownership-check.md +24 -0
  147. package/knowledge/decisions/security/a-vault-secret-redacts-on-serialization-and-throws-on-coercion.md +29 -0
  148. package/knowledge/decisions/security/a-virtual-user-catalogue-entry-is-filtered-by-scope-and-approval-is-denied-by-default.md +30 -0
  149. package/knowledge/decisions/security/a-virtual-user-environment-fails-closed.md +38 -0
  150. package/knowledge/decisions/security/a-virtual-user-never-runs-against-production.md +23 -0
  151. package/knowledge/decisions/security/a-virtual-user-reads-its-roles-from-the-apps-own-rpc-before-better-auth.md +27 -0
  152. package/knowledge/decisions/security/a-virtual-user-run-treats-an-unresolved-environment-as-production.md +41 -0
  153. package/knowledge/decisions/security/a-virtual-user-scopes-are-expanded-from-its-roles-once-at-run-preparation.md +25 -0
  154. package/knowledge/decisions/security/a-virtual-user-whose-roles-drift-from-the-declaration-refuses-to-run.md +32 -0
  155. package/knowledge/decisions/security/addon-screen-scopes-hide-and-do-not-enforce.md +20 -0
  156. package/knowledge/decisions/security/an-addon-header-can-only-narrow-the-session.md +26 -0
  157. package/knowledge/decisions/security/an-addon-instance-reads-only-the-secrets-and-credentials-it-is-named.md +33 -0
  158. package/knowledge/decisions/security/an-addon-may-reach-only-itself-and-the-addons-it-uses.md +16 -0
  159. package/knowledge/decisions/security/an-api-key-is-jwt-decoded-into-the-session.md +26 -0
  160. package/knowledge/decisions/security/an-external-virtual-user-caller-presents-one-signed-statement.md +38 -0
  161. package/knowledge/decisions/security/an-inbound-webhook-source-dispatches-only-verified-requests.md +31 -0
  162. package/knowledge/decisions/security/an-mcp-call-with-no-http-request-stays-anonymous.md +18 -0
  163. package/knowledge/decisions/security/an-omitted-user-id-addresses-the-platform-credential.md +32 -0
  164. package/knowledge/decisions/security/analytics-identity-is-stamped-from-the-session-not-the-event.md +24 -0
  165. package/knowledge/decisions/security/app-access-is-a-scope-tree-synthesised-from-virtual-users.md +26 -0
  166. package/knowledge/decisions/security/approval-policy-decides-who-answers-a-tool-call.md +27 -0
  167. package/knowledge/decisions/security/auth-false-on-a-session-function-warns-and-still-requires-one.md +25 -0
  168. package/knowledge/decisions/security/bearer-token-hashes-are-unpeppered-sha256.md +18 -0
  169. package/knowledge/decisions/security/consent-is-read-from-a-cookie-and-a-recognised-denial-counts-as-refusal.md +29 -0
  170. package/knowledge/decisions/security/cors-defaults-to-any-origin-and-refuses-the-wildcard-with-credentials.md +22 -0
  171. package/knowledge/decisions/security/credential-backends-share-one-conformance-suite-for-per-user-isolation.md +29 -0
  172. package/knowledge/decisions/security/each-stage-has-one-virtual-user-key-pair.md +27 -0
  173. package/knowledge/decisions/security/hmac-verification-fails-closed-on-empty-inputs.md +25 -0
  174. package/knowledge/decisions/security/index.md +88 -24
  175. package/knowledge/decisions/security/local-content-refuses-private-buckets-under-the-public-segment.md +21 -0
  176. package/knowledge/decisions/security/mail-is-allowlisted-before-a-virtual-user-run-sees-it.md +38 -0
  177. package/knowledge/decisions/security/mcp-resources-tools-and-prompts-take-sessionless-functions.md +18 -0
  178. package/knowledge/decisions/security/origin-locked-routes-match-the-origin-exactly.md +22 -0
  179. package/knowledge/decisions/security/oss-auth-works-without-pikku-studio-cloud.md +26 -0
  180. package/knowledge/decisions/security/outbound-webhooks-use-an-allowlist-when-configured.md +24 -0
  181. package/knowledge/decisions/security/pikku-carries-virtual-user-scopes-as-data-and-the-app-grants-them.md +35 -0
  182. package/knowledge/decisions/security/scoped-content-access-is-a-root-folder-with-longest-prefix-grants.md +31 -0
  183. package/knowledge/decisions/security/services-without-secrets-get-a-throwing-secrets-accessor.md +22 -0
  184. package/knowledge/decisions/security/shared-guards-refuse-to-mutate-or-shadow-a-system-role.md +34 -0
  185. package/knowledge/decisions/security/signed-uploads-are-verified-by-the-same-check-as-signed-reads.md +26 -0
  186. package/knowledge/decisions/security/system-role-scopes-must-be-declared-with-define-scope.md +24 -0
  187. package/knowledge/decisions/security/system-roles-are-additive-and-immutable.md +16 -0
  188. package/knowledge/decisions/security/the-channel-rpc-does-not-send-the-callers-session.md +21 -0
  189. package/knowledge/decisions/security/the-remote-jobs-inbox-fails-closed-without-a-secret.md +24 -0
  190. package/knowledge/decisions/security/the-remote-rpc-gate-fails-closed-and-binds-the-token-to-its-function.md +34 -0
  191. package/knowledge/decisions/security/the-workflow-status-stream-rechecks-ownership-on-every-poll.md +16 -0
  192. package/knowledge/decisions/security/two-credentials-on-one-key-must-share-a-read-mode.md +29 -0
  193. package/knowledge/decisions/security/verified-bearer-claims-are-pass-through-data-that-core-never-fills.md +23 -0
  194. package/knowledge/decisions/security/virtual-user-catalogue-excludes-the-machinery-that-runs-virtual-users.md +25 -0
  195. package/knowledge/decisions/security/{actor-flow-missing-approval-decisions-default-to-denied.md → virtual-user-conversation-missing-approval-decisions-default-to-denied.md} +7 -7
  196. package/knowledge/decisions/security/virtual-user-run-records-are-gated-behind-a-read-scope.md +18 -0
  197. package/knowledge/decisions/security/virtual-user-sign-in-does-not-exist-in-production.md +25 -0
  198. package/knowledge/decisions/security/virtual-user-sign-in-has-one-door.md +42 -0
  199. package/knowledge/decisions/security/{actor-sign-in-is-proven-by-set-cookie-not-a-non-empty-jar.md → virtual-user-sign-in-is-proven-by-set-cookie-not-a-non-empty-jar.md} +10 -8
  200. package/knowledge/decisions/security/virtual-user-sign-in-only-works-for-virtual-user-flagged-users.md +29 -0
  201. package/knowledge/decisions/security/workflow-helper-functions-are-sessionless-by-declaration.md +18 -0
  202. package/knowledge/decisions/security/{workflow-scenario-sessions-are-isolated-per-actor-and-per-scenario.md → workflow-scenario-sessions-are-isolated-per-virtual-user-and-per-scenario.md} +6 -6
  203. package/knowledge/decisions/security/workflow-scenario-steps-are-never-network-invocable.md +5 -5
  204. package/knowledge/decisions/security/{workflow-actor-steps-always-use-the-real-transport.md → workflow-virtual-user-steps-always-use-the-real-transport.md} +11 -11
  205. package/knowledge/decisions/security/writing-a-virtual-user-schedule-is-gated-by-its-own-scope.md +18 -0
  206. package/knowledge/index.md +0 -2
  207. package/knowledge/questions/a-bearer-jwt-with-no-identity-becomes-a-session.md +24 -0
  208. package/knowledge/questions/dev-quick-login-as-impersonation.md +25 -0
  209. package/knowledge/questions/does-a-delayed-rpc-run-as-the-session-it-was-scheduled-with.md +26 -0
  210. package/knowledge/questions/does-a-user-id-with-a-colon-read-another-users-credentials.md +27 -0
  211. package/knowledge/questions/does-a-wirecli-command-need-a-session-by-default.md +26 -0
  212. package/knowledge/questions/does-an-adversarial-in-scope-success-count-as-a-finding.md +26 -0
  213. package/knowledge/questions/does-approve-step-need-the-run-owners-session-or-the-gates-approvers.md +34 -0
  214. package/knowledge/questions/does-cors-origin-true-reflect-any-origin-with-credentials.md +20 -0
  215. package/knowledge/questions/does-skip-user-session-do-anything-on-a-channel.md +24 -0
  216. package/knowledge/questions/does-the-store-session-match-the-other-two.md +19 -0
  217. package/knowledge/questions/index.md +25 -2
  218. package/knowledge/questions/is-the-agent-score-worker-reachable-without-a-session.md +21 -0
  219. package/knowledge/questions/live-scheduled-tests-may-write.md +19 -0
  220. package/knowledge/questions/provision-virtual-users-has-no-caller-in-this-repo.md +23 -0
  221. package/knowledge/questions/remote-secret-refuses-requests-without-a-remote-token-on-every-path.md +32 -0
  222. package/knowledge/questions/should-a-middleware-set-session-persist-to-the-store.md +25 -0
  223. package/knowledge/questions/should-a-scoped-secret-view-throw-from-has-secret-for-a-disallowed-key.md +23 -0
  224. package/knowledge/questions/should-a-wrong-bearer-token-be-anonymous-or-refused.md +35 -0
  225. package/knowledge/questions/should-an-empty-webhook-signing-secret-send-unsigned.md +23 -0
  226. package/knowledge/questions/should-http-virtual-user-sessions-reset-between-scenarios-in-one-run.md +27 -0
  227. package/knowledge/questions/should-the-cookie-jar-scope-cookies-to-the-api-origin.md +26 -0
  228. package/knowledge/questions/should-voice-input-fetch-audio-urls-without-a-host-allowlist.md +20 -0
  229. package/knowledge/questions/staging-impersonation-rules.md +27 -0
  230. package/knowledge/questions/virtual-user-keys-on-cloud-stages-are-pikku-studios-to-build.md +34 -0
  231. package/knowledge/questions/virtual-user-statement-replay-is-per-process.md +20 -0
  232. package/knowledge/questions/what-an-impersonated-session-carries.md +22 -0
  233. package/package.json +3 -3
  234. package/src/public-surface.json +43 -47
  235. package/dist/services/persona-actor-secret.d.ts +0 -38
  236. package/dist/services/persona-actor-secret.js +0 -39
  237. package/dist/services/persona-sign-in.d.ts +0 -117
  238. package/dist/services/persona-sign-in.js +0 -154
  239. package/dist/wirings/actor-flow/index.d.ts +0 -2
  240. package/dist/wirings/actor-flow/run-conversation.d.ts +0 -36
  241. package/dist/wirings/persona/define-personas.d.ts +0 -32
  242. package/dist/wirings/persona/index.d.ts +0 -23
  243. package/dist/wirings/persona/index.js +0 -19
  244. package/knowledge/decisions/internals/actor-flow-conversations-seed-a-hidden-kickoff-message.md +0 -23
  245. package/knowledge/decisions/internals/actor-flow-verdicts-are-llm-self-evaluations.md +0 -25
  246. package/knowledge/decisions/internals/validate-checks-personas-through-a-shared-module.md +0 -43
  247. package/knowledge/decisions/security/actor-sign-in-only-works-for-actor-flagged-users.md +0 -31
  248. package/knowledge/decisions/security/an-actor-credential-is-derived-per-persona.md +0 -42
  249. package/knowledge/decisions/security/pikku-carries-actor-scopes-as-data-and-the-app-grants-them.md +0 -26
  250. /package/dist/wirings/{actor-flow/actor-flow.types.js → virtual-user/conversation/conversation.types.js} +0 -0
  251. /package/dist/wirings/{actor-flow → virtual-user/conversation}/index.js +0 -0
  252. /package/dist/wirings/{persona/persona.types.js → virtual-user/virtual-user-declaration.types.js} +0 -0
  253. /package/dist/wirings/{persona/persona-mailbox.js → virtual-user/virtual-user-mailbox.js} +0 -0
@@ -164,6 +164,10 @@ const executeRoute = async (services, matchedRoute, http, options) => {
164
164
  await originalClose();
165
165
  };
166
166
  }
167
+ response.onClose?.(() => {
168
+ channel.state = 'closed';
169
+ singletonServices.eventHub?.onChannelClosed(channelId);
170
+ });
167
171
  }
168
172
  const wire = {
169
173
  traceId: requestId,
@@ -185,6 +185,7 @@ export interface PikkuHTTPResponse<Out = unknown> {
185
185
  send?(data: string | ArrayBuffer | ArrayBufferView): this;
186
186
  redirect(location: string, status?: number): this;
187
187
  close?: () => void;
188
+ onClose?: (callback: () => void) => void;
188
189
  setMode?: (mode: 'stream') => void;
189
190
  flushHeaders?: () => void;
190
191
  }
@@ -14,6 +14,7 @@ export declare class PikkuFetchHTTPResponse implements PikkuHTTPResponse {
14
14
  send(data: any): this;
15
15
  redirect(location: string, status?: number): this;
16
16
  close(): this;
17
+ onClose(callback: () => void): void;
17
18
  toResponse(args?: Record<string, any>): Response;
18
19
  private createStream;
19
20
  }
@@ -8,6 +8,7 @@ export class PikkuFetchHTTPResponse {
8
8
  #send = null;
9
9
  #close = null;
10
10
  #cancelStream = null;
11
+ #onClose = [];
11
12
  setMode(mode) {
12
13
  this.#responseMode = 'stream';
13
14
  if (mode === 'stream') {
@@ -95,6 +96,15 @@ export class PikkuFetchHTTPResponse {
95
96
  }
96
97
  return this;
97
98
  }
99
+ onClose(callback) {
100
+ this.#onClose.push(callback);
101
+ }
102
+ #closed() {
103
+ const callbacks = this.#onClose;
104
+ this.#onClose = [];
105
+ for (const callback of callbacks)
106
+ callback();
107
+ }
98
108
  toResponse(args) {
99
109
  const cookieHeader = Array.from(this.#cookies.entries()).map(([name, { value, flags }]) => stringifySetCookie({ name, value, ...flags }, flags));
100
110
  cookieHeader.forEach((cookie) => this.#headers.append('Set-Cookie', cookie));
@@ -119,9 +129,11 @@ export class PikkuFetchHTTPResponse {
119
129
  return;
120
130
  closed = true;
121
131
  controller.close();
132
+ this.#closed();
122
133
  };
123
134
  this.#cancelStream = () => {
124
135
  closed = true;
136
+ this.#closed();
125
137
  };
126
138
  this.#send = send;
127
139
  this.#close = close;
@@ -1,3 +1,4 @@
1
+ import { PikkuFetchHTTPResponse } from './pikku-fetch-http-response.js';
1
2
  export function toWebRequest(req, baseUrl) {
2
3
  const proto = req.header('x-forwarded-proto') ?? 'http';
3
4
  const host = req.header('x-forwarded-host') ?? req.header('host') ?? 'localhost';
@@ -120,6 +121,12 @@ export async function applyWebResponse(res, webResponse) {
120
121
  if (setCookieValues.length > 0) {
121
122
  res.header('Set-Cookie', setCookieValues);
122
123
  }
124
+ if (webResponse.body &&
125
+ res instanceof PikkuFetchHTTPResponse &&
126
+ webResponse.headers.get('content-type')?.startsWith('text/event-stream')) {
127
+ res.send(webResponse.body);
128
+ return;
129
+ }
123
130
  const body = await readBody(webResponse);
124
131
  if (body !== null) {
125
132
  if (res.send) {
@@ -3,7 +3,7 @@ import type { CoreSystemRoles } from './role.types.js';
3
3
  * No-op function for declaring system roles.
4
4
  * This exists purely for TypeScript type checking and will be tree-shaken.
5
5
  * The CLI extracts metadata via AST parsing and generates a `SystemRoleName`
6
- * union, so a persona naming an undeclared role fails the build.
6
+ * union, so a virtual user naming an undeclared role fails the build.
7
7
  *
8
8
  * A system role is a role that ships with the product: the console may grant
9
9
  * it, but cannot rename, re-scope or delete it. Roles an admin composes in the
@@ -2,7 +2,7 @@
2
2
  * No-op function for declaring system roles.
3
3
  * This exists purely for TypeScript type checking and will be tree-shaken.
4
4
  * The CLI extracts metadata via AST parsing and generates a `SystemRoleName`
5
- * union, so a persona naming an undeclared role fails the build.
5
+ * union, so a virtual user naming an undeclared role fails the build.
6
6
  *
7
7
  * A system role is a role that ships with the product: the console may grant
8
8
  * it, but cannot rename, re-scope or delete it. Roles an admin composes in the
@@ -1,15 +1,15 @@
1
- export type ActorFlowApprovalPolicy = 'in-persona' | 'always' | 'never';
1
+ export type ConversationApprovalPolicy = 'in-virtual-user' | 'always' | 'never';
2
2
  export interface ConverseOptions<TAgentName extends string = string> {
3
3
  agent: TAgentName;
4
- /** What the actor is trying to get the agent to accomplish. */
4
+ /** What the virtual user is trying to get the agent to accomplish. */
5
5
  task: string;
6
- /** Natural-language success criterion the actor judges the conversation against. */
6
+ /** Natural-language success criterion the virtual user judges the conversation against. */
7
7
  evaluate: string;
8
- approvals?: ActorFlowApprovalPolicy;
8
+ approvals?: ConversationApprovalPolicy;
9
9
  model?: string;
10
10
  maxTurns?: number;
11
11
  }
12
- export interface ActorFlowVerdict {
12
+ export interface ConversationVerdict {
13
13
  passed: boolean;
14
14
  reasoning: string;
15
15
  transcript: string[];
@@ -0,0 +1,2 @@
1
+ export type { ConversationVerdict, ConverseOptions, TargetAgentDriver, } from './conversation.types.js';
2
+ export { runConversation, type RunConversationParams, type VirtualUserLLM, } from './run-conversation.js';
@@ -0,0 +1,36 @@
1
+ import type { ConversationApprovalPolicy, ConversationVerdict, TargetAgentDriver } from './conversation.types.js';
2
+ import type { ResolvedVirtualUser } from '../../../services/virtual-users-service.js';
3
+ import type { AgentRunnerParams, AgentStepResult } from '../../../services/agent-runner-service.js';
4
+ /** The LLM call the virtual user uses for its own turns/decisions/evaluation. */
5
+ export type VirtualUserLLM = (params: AgentRunnerParams) => Promise<AgentStepResult>;
6
+ export interface RunConversationParams {
7
+ /** The person being played — name, job title, personality. */
8
+ virtualUser: ResolvedVirtualUser;
9
+ /** The id they were declared under (for transcript labelling). */
10
+ virtualUserId: string;
11
+ /** What the virtual user is trying to get the target agent to accomplish. */
12
+ task: string;
13
+ /** Natural-language success criterion the virtual user evaluates at the end. */
14
+ evaluate: string;
15
+ /** How the virtual user answers the target agent's tool-approval requests. */
16
+ approvals?: ConversationApprovalPolicy;
17
+ /** Model the virtual user uses for its own turns/decisions. */
18
+ model: string;
19
+ /** Hard cap on conversation turns. Default 12. */
20
+ maxTurns?: number;
21
+ /** Hard cap on tool-approval rounds within a single target turn. Default 16. */
22
+ maxApprovalRounds?: number;
23
+ /** Transport that drives the target agent (HTTP in production). */
24
+ target: TargetAgentDriver;
25
+ /** The virtual user's own LLM. */
26
+ llm: VirtualUserLLM;
27
+ /** Display name of the target agent (transcript labelling). */
28
+ agentName: string;
29
+ }
30
+ /**
31
+ * Run a conversation: an LLM-driven virtual user holds a real multi-turn exchange
32
+ * with a target agent (driven via the injected transport), answers the target's
33
+ * tool-approval requests in-virtual-user, then evaluates whether the task was met.
34
+ * Deterministic checks are the caller's responsibility.
35
+ */
36
+ export declare function runConversation(params: RunConversationParams): Promise<ConversationVerdict>;
@@ -1,5 +1,5 @@
1
- /** One turn the actor takes: the message to send and whether it's finished. */
2
- const ACTOR_TURN_SCHEMA = {
1
+ /** One turn the virtual user takes: the message to send and whether it's finished. */
2
+ const VIRTUAL_USER_TURN_SCHEMA = {
3
3
  type: 'object',
4
4
  properties: {
5
5
  message: { type: 'string' },
@@ -7,7 +7,7 @@ const ACTOR_TURN_SCHEMA = {
7
7
  },
8
8
  required: ['message', 'done'],
9
9
  };
10
- /** The actor's approve/deny decision for each pending tool request. */
10
+ /** The virtual user's approve/deny decision for each pending tool request. */
11
11
  const APPROVAL_DECISION_SCHEMA = {
12
12
  type: 'object',
13
13
  properties: {
@@ -26,7 +26,7 @@ const APPROVAL_DECISION_SCHEMA = {
26
26
  },
27
27
  required: ['decisions'],
28
28
  };
29
- /** The actor's final verdict on whether the task was accomplished. */
29
+ /** The virtual user's final verdict on whether the task was accomplished. */
30
30
  const EVALUATION_SCHEMA = {
31
31
  type: 'object',
32
32
  properties: {
@@ -60,25 +60,25 @@ function readObject(result) {
60
60
  }
61
61
  return null;
62
62
  }
63
- function actorInstructions(persona, task) {
63
+ function virtualUserConversationInstructions(virtualUser, task) {
64
64
  return [
65
65
  `You are role-playing a real user interacting with an AI assistant. Stay in character at all times — you are the user, not the assistant.`,
66
- `Your name is ${persona.name}.`,
67
- persona.jobTitle ? `Your role: ${persona.jobTitle}.` : '',
68
- persona.personality
69
- ? `Your personality and communication style: ${persona.personality}. Match this tone, vocabulary, and level of detail exactly.`
66
+ `Your name is ${virtualUser.name}.`,
67
+ virtualUser.jobTitle ? `Your role: ${virtualUser.jobTitle}.` : '',
68
+ virtualUser.personality
69
+ ? `Your personality and communication style: ${virtualUser.personality}. Match this tone, vocabulary, and level of detail exactly.`
70
70
  : '',
71
71
  `Your goal in this conversation: ${task}.`,
72
72
  `Send one message at a time. Set "done" to true only once your goal is clearly accomplished, or clearly impossible.`,
73
- // knowledge: decisions/internals/the-actor-prompt-says-json-because-of-json-object-mode.md
73
+ // knowledge: decisions/internals/the-virtual-user-prompt-says-json-because-of-json-object-mode.md
74
74
  `Reply with json matching the schema you are given, and nothing else.`,
75
75
  ]
76
76
  .filter(Boolean)
77
77
  .join('\n');
78
78
  }
79
- /** Route the target agent's pending tool approvals through the actor. */
79
+ /** Route the target agent's pending tool approvals through the virtual user. */
80
80
  async function decideApprovals(params, instructions, pending) {
81
- const policy = params.approvals ?? 'in-persona';
81
+ const policy = params.approvals ?? 'in-virtual-user';
82
82
  if (policy === 'always') {
83
83
  return pending.map((p) => ({ toolCallId: p.toolCallId, approved: true }));
84
84
  }
@@ -90,7 +90,7 @@ async function decideApprovals(params, instructions, pending) {
90
90
  .join('\n');
91
91
  const result = await params.llm({
92
92
  model: params.model,
93
- instructions: `${instructions}\nThe assistant is asking permission to run tools on your behalf. Decide whether YOU, as this actor, would allow each one.`,
93
+ instructions: `${instructions}\nThe assistant is asking permission to run tools on your behalf. Decide whether YOU, as this virtual user, would allow each one.`,
94
94
  messages: [
95
95
  msg('user', `The assistant wants to run these tools:\n${summary}\nApprove or deny each toolCallId.`),
96
96
  ],
@@ -106,7 +106,7 @@ async function decideApprovals(params, instructions, pending) {
106
106
  return { toolCallId: p.toolCallId, approved: match?.approved ?? false };
107
107
  });
108
108
  }
109
- /** Drive the target to a non-suspended reply, routing approvals to the actor. */
109
+ /** Drive the target to a non-suspended reply, routing approvals to the virtual user. */
110
110
  async function converseWithTarget(params, instructions, message) {
111
111
  const maxRounds = params.maxApprovalRounds ?? DEFAULT_MAX_APPROVAL_ROUNDS;
112
112
  let reply = await params.target.run(message);
@@ -124,40 +124,40 @@ async function converseWithTarget(params, instructions, message) {
124
124
  return reply;
125
125
  }
126
126
  /**
127
- * Run a conversation: an LLM-driven actor holds a real multi-turn exchange
127
+ * Run a conversation: an LLM-driven virtual user holds a real multi-turn exchange
128
128
  * with a target agent (driven via the injected transport), answers the target's
129
- * tool-approval requests in-persona, then evaluates whether the task was met.
129
+ * tool-approval requests in-virtual-user, then evaluates whether the task was met.
130
130
  * Deterministic checks are the caller's responsibility.
131
131
  */
132
132
  export async function runConversation(params) {
133
133
  const maxTurns = params.maxTurns ?? DEFAULT_MAX_TURNS;
134
- const instructions = actorInstructions(params.persona, params.task);
135
- // Seed a kickoff so the very first actor turn has a non-empty message list
136
- // (providers reject an empty prompt). It's an instruction TO the actor, so
134
+ const instructions = virtualUserConversationInstructions(params.virtualUser, params.task);
135
+ // Seed a kickoff so the very first virtual user turn has a non-empty message list
136
+ // (providers reject an empty prompt). It's an instruction TO the virtual user, so
137
137
  // it never appears in the transcript.
138
- const actorMessages = [
138
+ const virtualUserMessages = [
139
139
  msg('user', 'Begin the conversation now — send your first message to the assistant to work towards your goal.'),
140
140
  ];
141
141
  const transcript = [];
142
142
  for (let turn = 0; turn < maxTurns; turn++) {
143
- const actorResult = await params.llm({
143
+ const virtualUserResult = await params.llm({
144
144
  model: params.model,
145
145
  instructions,
146
- messages: actorMessages,
146
+ messages: virtualUserMessages,
147
147
  tools: [],
148
148
  maxSteps: 1,
149
149
  toolChoice: 'none',
150
- outputSchema: ACTOR_TURN_SCHEMA,
150
+ outputSchema: VIRTUAL_USER_TURN_SCHEMA,
151
151
  });
152
- const turnData = readObject(actorResult);
153
- const actorMessage = turnData?.message?.trim();
154
- if (!actorMessage) {
152
+ const turnData = readObject(virtualUserResult);
153
+ const virtualUserMessage = turnData?.message?.trim();
154
+ if (!virtualUserMessage) {
155
155
  break;
156
156
  }
157
- actorMessages.push(msg('assistant', actorMessage));
158
- transcript.push(`${params.persona.name}: ${actorMessage}`);
159
- const reply = await converseWithTarget(params, instructions, actorMessage);
160
- actorMessages.push(msg('user', reply.text ?? ''));
157
+ virtualUserMessages.push(msg('assistant', virtualUserMessage));
158
+ transcript.push(`${params.virtualUser.name}: ${virtualUserMessage}`);
159
+ const reply = await converseWithTarget(params, instructions, virtualUserMessage);
160
+ virtualUserMessages.push(msg('user', reply.text ?? ''));
161
161
  transcript.push(`${params.agentName}: ${reply.text ?? ''}`);
162
162
  if (turnData?.done) {
163
163
  break;
@@ -0,0 +1,32 @@
1
+ import type { CoreVirtualUsers } from './virtual-user-declaration.types.js';
2
+ /**
3
+ * No-op function for declaring virtual users.
4
+ * This exists purely for TypeScript type checking and will be tree-shaken.
5
+ * The CLI extracts metadata via AST parsing and generates a `VirtualUserId` union
6
+ * and a `virtual-users.gen.json` the console and `pikku virtual-user run` read off disk —
7
+ * describing, listing or running one never has to load the app.
8
+ *
9
+ * Declaring is not running: a virtual user that exists only to be acted upon
10
+ * (the account an admin bans, the colleague a document is shared with) is
11
+ * seeded and never run.
12
+ *
13
+ * Exactly one `defineVirtualUsers(...)` is allowed per codebase, so there is one
14
+ * place to read the cast from and one place to add to. A second call — even in
15
+ * the same file — fails the build.
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * defineVirtualUsers({
20
+ * susan: {
21
+ * name: 'Susan',
22
+ * jobTitle: 'Buys for a small café',
23
+ * roles: ['buyer'],
24
+ * personality: 'Hunts cheap deals. Tries three coupon codes before giving up.',
25
+ * goals: ['Get the weekly order in under five minutes'],
26
+ * disposition: 'careless',
27
+ * account: {},
28
+ * },
29
+ * })
30
+ * ```
31
+ */
32
+ export declare const defineVirtualUsers: (_config: CoreVirtualUsers) => void;
@@ -1,21 +1,21 @@
1
1
  /**
2
- * No-op function for declaring personas.
2
+ * No-op function for declaring virtual users.
3
3
  * This exists purely for TypeScript type checking and will be tree-shaken.
4
- * The CLI extracts metadata via AST parsing and generates a `PersonaId` union
5
- * and a `personas.gen.json` the console and `pikku persona run` read off disk —
4
+ * The CLI extracts metadata via AST parsing and generates a `VirtualUserId` union
5
+ * and a `virtual-users.gen.json` the console and `pikku virtual-user run` read off disk —
6
6
  * describing, listing or running one never has to load the app.
7
7
  *
8
- * `definePersonas` rather than `defineVirtualUsers` because declaring is not
9
- * running: a persona that exists only to be acted upon (the account an admin
10
- * bans, the colleague a document is shared with) is seeded and never run.
8
+ * Declaring is not running: a virtual user that exists only to be acted upon
9
+ * (the account an admin bans, the colleague a document is shared with) is
10
+ * seeded and never run.
11
11
  *
12
- * Exactly one `definePersonas(...)` is allowed per codebase, so there is one
12
+ * Exactly one `defineVirtualUsers(...)` is allowed per codebase, so there is one
13
13
  * place to read the cast from and one place to add to. A second call — even in
14
14
  * the same file — fails the build.
15
15
  *
16
16
  * @example
17
17
  * ```typescript
18
- * definePersonas({
18
+ * defineVirtualUsers({
19
19
  * susan: {
20
20
  * name: 'Susan',
21
21
  * jobTitle: 'Buys for a small café',
@@ -28,4 +28,4 @@
28
28
  * })
29
29
  * ```
30
30
  */
31
- export const definePersonas = (_config) => { };
31
+ export const defineVirtualUsers = (_config) => { };
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Virtual user module exports.
3
3
  *
4
- * A virtual user is an LLM playing a persona that signs into a *running* stage
4
+ * A virtual user is an LLM that signs into a *running* stage
5
5
  * and works its API in character — non-deterministically, with a budget, and
6
6
  * with oracles watching what comes back. It is not a test runner: nothing here
7
7
  * asserts an expected outcome, because the point is the outcomes nobody thought
@@ -9,24 +9,47 @@
9
9
  *
10
10
  * Everything it needs is derived from what a pikku project already generates —
11
11
  * the function meta becomes the catalogue, the scenario meta becomes the
12
- * intents, the declared personas become the identities — so adopting it is
12
+ * intents, the declared virtual users become the identities — so adopting it is
13
13
  * configuration rather than authoring.
14
14
  *
15
15
  * The engine is transport-agnostic: the virtual user drives an
16
- * {@link VirtualUserTarget}, which in production is an `HttpPersona`
16
+ * {@link VirtualUserTarget}, which in production is an `HttpVirtualUser`
17
17
  * signed in as a real user against staging or production.
18
18
  */
19
19
  export type { ApiCatalogueEntry, IntentRecord, IntentSource, StepRecord, VirtualUserBudget, VirtualUserDisposition, VirtualUserFinding, VirtualUserRunResult, VirtualUserTarget, } from './virtual-user.types.js';
20
20
  export { PRODUCTION_DISPOSITION } from './virtual-user.types.js';
21
21
  export { runVirtualUser, type RunVirtualUserParams, } from './run-virtual-user.js';
22
- export { personaScopes, prepareVirtualUserRun, type VirtualUserPreparation, } from './prepare-virtual-user-run.js';
22
+ export { virtualUserScopes, prepareVirtualUserRun, type VirtualUserPreparation, } from './prepare-virtual-user-run.js';
23
23
  export type { VirtualUserRunOutcome, VirtualUserRunRecord, VirtualUserRunStart, VirtualUserRunStore, } from './virtual-user-run-store.js';
24
24
  export type { VirtualUserScheduleInput, VirtualUserScheduleRecord, VirtualUserScheduleStore, } from './virtual-user-schedule-store.js';
25
25
  export { DEFAULT_MAX_INTERVAL_MS, DEFAULT_MIN_INTERVAL_MS, isDue, nextRunAt, STALE_RUN_AFTER_MS, tickVirtualUserSchedules, type VirtualUserTickParams, type VirtualUserTickResult, } from './virtual-user-schedule.js';
26
26
  export { DISPOSITIONS, dispositionProfile, type DispositionProfile, type VirtualUserTuning, } from './virtual-user-dispositions.js';
27
27
  export { catalogueClassification, catalogueLookup, isReadOnly, reachableCatalogue, unreachableCatalogue, } from './virtual-user-catalogue.js';
28
28
  export { type AgentReachability, type ReachableAgent, } from './virtual-user-agents.js';
29
- export { IntentStack, intentsForPersona } from './virtual-user-intents.js';
29
+ export { IntentStack, intentsForVirtualUser } from './virtual-user-intents.js';
30
30
  export { deriveCatalogue, deriveIntents, type SchemaMap, } from './virtual-user-derive.js';
31
- export { personaVirtualUserTarget, type PersonaTargetOptions, } from './virtual-user-target.js';
32
- export { executeVirtualUserRun, logVirtualUserTick, requireVirtualUserRunStore, requireVirtualUserScheduleStore, runnablePersona, serializeVirtualUserRun, serializeVirtualUserSchedule, serializeVirtualUserSteps, signInPathFor, startVirtualUserRun, VIRTUAL_USER_VARIABLES, virtualUserScheduleRunInput, writeVirtualUserSchedule, type ExecuteVirtualUserRunParams, type ScaffoldPersonas, type StartedVirtualUserRun, type StartVirtualUserRunParams, type WriteVirtualUserScheduleParams, } from './virtual-user-scaffold.js';
31
+ export { virtualUserTarget, type VirtualUserTargetOptions, } from './virtual-user-target.js';
32
+ export { executeVirtualUserRun, logVirtualUserTick, requireVirtualUserRunStore, requireVirtualUserScheduleStore, runnableVirtualUser, serializeVirtualUserRun, serializeVirtualUserSchedule, serializeVirtualUserSteps, startVirtualUserRun, VIRTUAL_USER_VARIABLES, virtualUserScheduleRunInput, writeVirtualUserSchedule, type ExecuteVirtualUserRunParams, type ScaffoldVirtualUsers, type StartedVirtualUserRun, type StartVirtualUserRunParams, type WriteVirtualUserScheduleParams, } from './virtual-user-scaffold.js';
33
+ export { defineVirtualUsers } from './define-virtual-users.js';
34
+ export { isRunnableVirtualUser, roleMismatchMessage, runnableVirtualUsers, validateAndBuildVirtualUsersMeta, verifyVirtualUserRoles, } from './validate-virtual-users.js';
35
+ export type { RoleVerification } from './validate-virtual-users.js';
36
+ export { virtualUserEnvironmentErrors, virtualUserEnvironmentRefusal, } from './virtual-user-environments.js';
37
+ export type { VirtualUserEnvironment, VirtualUserEnvironmentSubject, } from './virtual-user-environments.js';
38
+ export { virtualUserEmail, virtualUserEmails } from './virtual-user-email.js';
39
+ export { APP_SCOPE_ROOT, appScopeId, buildAppScopeDefinition, } from './virtual-user-app-scopes.js';
40
+ export type { MailboxAllowlist, VirtualUserMailbox, ReceivedEmail, } from './virtual-user-mailbox.js';
41
+ export type { CoreVirtualUser, CoreVirtualUsers, VirtualUserAccountMeta, VirtualUserDefinitions, VirtualUserMeta, VirtualUsersMeta, } from './virtual-user-declaration.types.js';
42
+ /**
43
+ * Signing in as a virtual user and talking to a stage over HTTP.
44
+ *
45
+ * Deliberately reached through this entry point rather than `@pikku/core/services`.
46
+ * `HttpVirtualUser` pulls in the conversation runner and, through it, the
47
+ * agent runner — none of which a production server has any use for. Exporting it
48
+ * from the services barrel put that chain in the module graph of every app that
49
+ * imports services, which only a bundler could remove and an unbundled Node or
50
+ * Lambda deploy would load outright.
51
+ */
52
+ export { HttpVirtualUser, createHttpVirtualUsers, type HttpVirtualUsersConfig, } from '../../services/http-virtual-users.js';
53
+ export { statementSignIn, inProcessSignIn, authMount, type VirtualUserSignIn, type VirtualUserStatementMint, type StatementSignInOptions, type InProcessAuth, } from '../../services/virtual-user-sign-in.js';
54
+ export { createCookieJar, type ScenarioCookieJar, } from '../../services/scenario-cookie-jar.js';
55
+ export { postScenarioJson, readScenarioHttpResponse, } from '../../services/virtual-users-service.js';
@@ -1,10 +1,29 @@
1
1
  export { PRODUCTION_DISPOSITION } from './virtual-user.types.js';
2
2
  export { runVirtualUser, } from './run-virtual-user.js';
3
- export { personaScopes, prepareVirtualUserRun, } from './prepare-virtual-user-run.js';
3
+ export { virtualUserScopes, prepareVirtualUserRun, } from './prepare-virtual-user-run.js';
4
4
  export { DEFAULT_MAX_INTERVAL_MS, DEFAULT_MIN_INTERVAL_MS, isDue, nextRunAt, STALE_RUN_AFTER_MS, tickVirtualUserSchedules, } from './virtual-user-schedule.js';
5
5
  export { DISPOSITIONS, dispositionProfile, } from './virtual-user-dispositions.js';
6
6
  export { catalogueClassification, catalogueLookup, isReadOnly, reachableCatalogue, unreachableCatalogue, } from './virtual-user-catalogue.js';
7
- export { IntentStack, intentsForPersona } from './virtual-user-intents.js';
7
+ export { IntentStack, intentsForVirtualUser } from './virtual-user-intents.js';
8
8
  export { deriveCatalogue, deriveIntents, } from './virtual-user-derive.js';
9
- export { personaVirtualUserTarget, } from './virtual-user-target.js';
10
- export { executeVirtualUserRun, logVirtualUserTick, requireVirtualUserRunStore, requireVirtualUserScheduleStore, runnablePersona, serializeVirtualUserRun, serializeVirtualUserSchedule, serializeVirtualUserSteps, signInPathFor, startVirtualUserRun, VIRTUAL_USER_VARIABLES, virtualUserScheduleRunInput, writeVirtualUserSchedule, } from './virtual-user-scaffold.js';
9
+ export { virtualUserTarget, } from './virtual-user-target.js';
10
+ export { executeVirtualUserRun, logVirtualUserTick, requireVirtualUserRunStore, requireVirtualUserScheduleStore, runnableVirtualUser, serializeVirtualUserRun, serializeVirtualUserSchedule, serializeVirtualUserSteps, startVirtualUserRun, VIRTUAL_USER_VARIABLES, virtualUserScheduleRunInput, writeVirtualUserSchedule, } from './virtual-user-scaffold.js';
11
+ export { defineVirtualUsers } from './define-virtual-users.js';
12
+ export { isRunnableVirtualUser, roleMismatchMessage, runnableVirtualUsers, validateAndBuildVirtualUsersMeta, verifyVirtualUserRoles, } from './validate-virtual-users.js';
13
+ export { virtualUserEnvironmentErrors, virtualUserEnvironmentRefusal, } from './virtual-user-environments.js';
14
+ export { virtualUserEmail, virtualUserEmails } from './virtual-user-email.js';
15
+ export { APP_SCOPE_ROOT, appScopeId, buildAppScopeDefinition, } from './virtual-user-app-scopes.js';
16
+ /**
17
+ * Signing in as a virtual user and talking to a stage over HTTP.
18
+ *
19
+ * Deliberately reached through this entry point rather than `@pikku/core/services`.
20
+ * `HttpVirtualUser` pulls in the conversation runner and, through it, the
21
+ * agent runner — none of which a production server has any use for. Exporting it
22
+ * from the services barrel put that chain in the module graph of every app that
23
+ * imports services, which only a bundler could remove and an unbundled Node or
24
+ * Lambda deploy would load outright.
25
+ */
26
+ export { HttpVirtualUser, createHttpVirtualUsers, } from '../../services/http-virtual-users.js';
27
+ export { statementSignIn, inProcessSignIn, authMount, } from '../../services/virtual-user-sign-in.js';
28
+ export { createCookieJar, } from '../../services/scenario-cookie-jar.js';
29
+ export { postScenarioJson, readScenarioHttpResponse, } from '../../services/virtual-users-service.js';
@@ -5,19 +5,19 @@ import { type SchemaMap } from './virtual-user-derive.js';
5
5
  import { type AgentReachability, type ReachableAgent } from './virtual-user-agents.js';
6
6
  import type { ApiCatalogueEntry, IntentSource } from './virtual-user.types.js';
7
7
  /**
8
- * The scopes a persona holds, resolved through its roles.
8
+ * The scopes a virtual user holds, resolved through its roles.
9
9
  *
10
- * Roles are the only thing a persona declares; scopes are what a function
10
+ * Roles are the only thing a virtual user declares; scopes are what a function
11
11
  * checks. Narrowing a virtual user's catalogue needs the second, so the
12
12
  * expansion happens once, here, against the same `defineSystemRole` definitions
13
13
  * the seed grants from.
14
14
  */
15
- export declare const personaScopes: (persona: {
15
+ export declare const virtualUserScopes: (virtualUser: {
16
16
  roles?: readonly string[];
17
17
  }, roleScopes: Record<string, readonly string[]>) => string[];
18
18
  /** Everything a run needs that is derived rather than decided. */
19
19
  export interface VirtualUserPreparation {
20
- /** Every RPC the app exposes, narrowed to what this persona can reach. */
20
+ /** Every RPC the app exposes, narrowed to what this virtual user can reach. */
21
21
  catalogue: ApiCatalogueEntry[];
22
22
  intents: IntentSource[];
23
23
  scopes: string[];
@@ -27,18 +27,18 @@ export interface VirtualUserPreparation {
27
27
  * Derive what a virtual user needs from what the project already generates.
28
28
  *
29
29
  * Shared because there are two callers with the same problem and different
30
- * sources for it: `pikku persona run` reads the inspector state at build time,
30
+ * sources for it: `pikku virtual-user run` reads the inspector state at build time,
31
31
  * and the scaffolded `runVirtualUser` RPC reads `metaService` at runtime. They
32
- * must agree — a persona whose catalogue is narrower over RPC than on the CLI
32
+ * must agree — a virtual user whose catalogue is narrower over RPC than on the CLI
33
33
  * finds different things from the same seed, which is exactly the property a
34
34
  * seed exists to give.
35
35
  *
36
36
  * Nothing here is authored for the virtual user's benefit: the function meta is
37
37
  * the catalogue, the scenario meta is the intents, and the role definitions are
38
- * what turn a persona's declared roles into the scopes a function checks.
38
+ * what turn a virtual user's declared roles into the scopes a function checks.
39
39
  */
40
40
  export declare const prepareVirtualUserRun: (input: {
41
- persona: {
41
+ virtualUser: {
42
42
  roles?: readonly string[];
43
43
  };
44
44
  functionsMeta: FunctionsMeta;
@@ -2,16 +2,16 @@ import { flattenSystemRoleDefinitions } from '../role/validate-role-definitions.
2
2
  import { deriveCatalogue, deriveIntents, } from './virtual-user-derive.js';
3
3
  import { reachableAgents, } from './virtual-user-agents.js';
4
4
  /**
5
- * The scopes a persona holds, resolved through its roles.
5
+ * The scopes a virtual user holds, resolved through its roles.
6
6
  *
7
- * Roles are the only thing a persona declares; scopes are what a function
7
+ * Roles are the only thing a virtual user declares; scopes are what a function
8
8
  * checks. Narrowing a virtual user's catalogue needs the second, so the
9
9
  * expansion happens once, here, against the same `defineSystemRole` definitions
10
10
  * the seed grants from.
11
11
  */
12
- export const personaScopes = (persona, roleScopes) => {
12
+ export const virtualUserScopes = (virtualUser, roleScopes) => {
13
13
  const scopes = new Set();
14
- for (const role of persona.roles ?? []) {
14
+ for (const role of virtualUser.roles ?? []) {
15
15
  for (const scope of roleScopes[role] ?? []) {
16
16
  scopes.add(scope);
17
17
  }
@@ -22,15 +22,15 @@ export const personaScopes = (persona, roleScopes) => {
22
22
  * Derive what a virtual user needs from what the project already generates.
23
23
  *
24
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,
25
+ * sources for it: `pikku virtual-user run` reads the inspector state at build time,
26
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
27
+ * must agree — a virtual user whose catalogue is narrower over RPC than on the CLI
28
28
  * finds different things from the same seed, which is exactly the property a
29
29
  * seed exists to give.
30
30
  *
31
31
  * Nothing here is authored for the virtual user's benefit: the function meta is
32
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.
33
+ * what turn a virtual user's declared roles into the scopes a function checks.
34
34
  */
35
35
  export const prepareVirtualUserRun = (input) => {
36
36
  const catalogue = deriveCatalogue(input.functionsMeta, input.schemas ?? {});
@@ -40,10 +40,10 @@ export const prepareVirtualUserRun = (input) => {
40
40
  for (const role of flattenSystemRoleDefinitions(Array.isArray(declared) ? declared : Object.values(declared))) {
41
41
  roleScopes[role.name] = role.scopes;
42
42
  }
43
- const scopes = personaScopes(input.persona, roleScopes);
43
+ const scopes = virtualUserScopes(input.virtualUser, roleScopes);
44
44
  // Gated by the same scopes as the RPCs, because an agent is reached rather
45
45
  // than declared: `CoreAgent.scopes` is checked against the session, so a
46
- // persona finds the specialists its roles unlock and no others.
46
+ // virtual user finds the specialists its roles unlock and no others.
47
47
  const agents = reachableAgents(input.agentsMeta ?? {}, scopes);
48
48
  return { catalogue, intents, scopes, agents };
49
49
  };
@@ -1,5 +1,5 @@
1
- import type { ResolvedPersona } from '../../services/personas-service.js';
2
- import type { ActorLLM } from '../actor-flow/run-conversation.js';
1
+ import type { ResolvedVirtualUser } from '../../services/virtual-users-service.js';
2
+ import type { VirtualUserLLM } from './conversation/run-conversation.js';
3
3
  import { type VirtualUserTuning } from './virtual-user-dispositions.js';
4
4
  import type { ApiCatalogueEntry, IntentSource, VirtualUserBudget, VirtualUserDisposition, VirtualUserFinding, VirtualUserRunResult, VirtualUserTally, VirtualUserTarget } from './virtual-user.types.js';
5
5
  /** What an app-specific oracle is shown about one call. */
@@ -15,9 +15,9 @@ export interface VirtualUserCallContext {
15
15
  }
16
16
  export interface RunVirtualUserParams {
17
17
  /** The person being run — name, job title, personality, goals. */
18
- persona: ResolvedPersona;
18
+ virtualUser: ResolvedVirtualUser;
19
19
  /** The id they were declared under, as the intent sources refer to them. */
20
- personaId: string;
20
+ virtualUserId: string;
21
21
  /** How it behaves. Default `realistic`. */
22
22
  disposition?: VirtualUserDisposition;
23
23
  /** Per-user overrides for that disposition's dials. */
@@ -31,7 +31,7 @@ export interface RunVirtualUserParams {
31
31
  /** The transport it acts through. */
32
32
  target: VirtualUserTarget;
33
33
  /** The user's own LLM. */
34
- llm: ActorLLM;
34
+ llm: VirtualUserLLM;
35
35
  model: string;
36
36
  budget?: VirtualUserBudget;
37
37
  /**
@@ -60,7 +60,7 @@ export interface RunVirtualUserParams {
60
60
  /** Ids and slugs remembered from an earlier run, for a `stale` user. */
61
61
  memory?: Record<string, string>;
62
62
  /**
63
- * The scopes this persona actually holds, resolved from its roles at sign-in.
63
+ * The scopes this virtual user actually holds, resolved from its roles at sign-in.
64
64
  *
65
65
  * Used two ways: to narrow a large catalogue to what it is entitled to reach,
66
66
  * and as an oracle — a call whose scopes it does not hold that nonetheless